home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / LIBRARY / DSUTIL12 / HD-MBOOT / HD-MBOOT.PAS < prev    next >
Pascal/Delphi Source File  |  1993-11-22  |  84KB  |  2,138 lines

  1. {-----------------------------------------------------------------------}
  2. { PROJECT        NON-PROFIT HIGH QUALITY PROFESSIONAL SOFTWARE,  }
  3. {            AVAILABLE FOR ALL WORLD                }
  4. { LIBRARY        SYSTEM UTILITIES                                }
  5. { MODULE        OPERATING-SYSTEM-LOADER FROM HARD DISK          }
  6. { FILE NAME        HD-MBOOT.PAS                    }
  7. { PURPOSE        OS-loader from the fixed disk with a setup of   }
  8. {                       the hard disk drive(s) type(s) at the boot time }
  9. { VERSION        1.11                        }
  10. { DATE            22-Nov-93                    }
  11. { DESIGN        Dmitry Stefankov                }
  12. { IMPLEMENTATION    Dmitry Stefankov                 }
  13. { COMPANY        Freelance Software Engineer            }
  14. { ADDRESS        Isakowskogo str, 4-2-30                }
  15. {            Moscow, 123181                    }
  16. {            USSR                        }
  17. {            Tel. 007 (095) 944-6304                }
  18. { COPYRIGHT NOTICE    Copyright (C) 1987-1993, Dmitry Stefankov    }
  19. { RESTRICTED RIGHTS    AVAILABLE ONLY FOR FREE DISTRIBUTION,           }
  20. {            NOT FOR COMMERCIAL PURPOSE            }
  21. { COMPUTER        IBM PC or compatible                }
  22. { OPERATING SYSTEM    MS/PC-DOS Version 3.30 or higher        }
  23. { COMPILER        Turbo Pascal Version 6.0            }
  24. {                       (Borland International Inc.)  or compatible     }
  25. { ASSEMBLY LANGUAGE    Microsoft MASM 5.10 or compatible               }
  26. { LINKER        Turbo Pascal internal                           }
  27. { ARGUMENTS        None                                            }
  28. { RETURN        See error return codes definitions        }
  29. { REQUIRES        Source Code Files                               }
  30. {                       NONE                                            }
  31. {                       External Object Files                           }
  32. {                       NONE                                            }
  33. {            Maintence Project Files                }
  34. {            NONE                        }
  35. { NATURAL LANGUAGE      English Language                                 }
  36. { SPECIAL        None                        }
  37. { DESCRIPTION           Bootstrap procedure                             }
  38. {                       1. Setup work registers and relocate code       }
  39. {                          to avoid overwriting                         }
  40. {                       2. If drive 0 type must be installed            }
  41. {                            then  setup BIOS vector $41                }
  42. {                                  call disk BIOS set dsk parms fn      }
  43. {                       3. If drive 1 type must be installed            }
  44. {                            then  setup BIOS vector $46                }
  45. {                                  call disk BIOS set dsk parms fn      }
  46. {                       4. If boot drive prompt is active               }
  47. {                             then  ask user about boot drive           }
  48. {                                  (hard disk 0 or floppy diskette 0)   }
  49. {                             otherwise try to load OS from hard disk 0 }
  50. {                       Main program                                    }
  51. {                       1. Read Master Boot Record.                     }
  52. {                       2. Copy already installed drive types/settings  }
  53. {                          if found and user will confirm               }
  54. {                       3. Enter user command menu                      }
  55. {              3.1. Execute user command or return error     }
  56. {                              with description of reason               }
  57. {                      NOTE: Please use source code as best description }
  58. { REVISION HISTORY    Dima Stefankov (DS)                }
  59. {               1.00   08-Sep-93  DS  initial release        }
  60. {                       1.01   24-Sep-93  DS  added user menu           }
  61. {            1.10   19-Oct-93  DS  updated documentation and }
  62. {                          fixed some bugs        }
  63. {            1.11   22-Nov-93  DS  remove 286 code generation}
  64. {                          switch for our MBR    }
  65. {-----------------------------------------------------------------------}
  66.  
  67.  
  68. {*======================= PROGRAM HEADER PART ==========================*}
  69.  
  70. PROGRAM   HARD_DISK_MASTER_BOOT_RECORD;
  71.  
  72.  
  73. {*** other modules ***}
  74. USES
  75.     Dos;
  76.  
  77.  
  78. {** switches for compilation **}
  79. {$S-}        {*  stack checking   *}
  80. {$R-}           {*  range checking   *}
  81.  
  82. {* generate version for loader code debugging *}
  83. {***$DEFINE  DebugVersion}
  84. {***$DEFINE FormatLogicTest}
  85. {***$DEFINE VerifyLogicTest}
  86. {$DEFINE AdvancedUserVersion}
  87. {***$DEFINE  DriveType2}
  88. {***$DEFINE  PresentDiskDrive0}
  89. {***$DEFINE  PresentDiskDrive1}
  90.  
  91.  
  92. {*========================== CONSTANTS PART ============================*}
  93.  
  94. CONST
  95.      { program definitions }
  96.        asPurpose               =       'HD-MasterBoot';
  97.        asVersion               =       '1.11';
  98.        asAuthor                =       'Dima Stefankov';
  99.        asCopyright             =       'Copyright (c) 1987, 1993';
  100.        asProgram               =       'HD-MBoot';
  101.        asProgramPrompt         =       asProgram+': ';
  102.  
  103.    {**** !!DON'T CHANGE THESE MESSAGES WITHOUT PRIOR WRITTEN PERMISSION!! ****}
  104.       asSacredMsg_A           =       asProgramPrompt+' Reminder Screen';
  105.       asSacredMsg_B           =       ' ****************************************************************************';
  106.       asSacredMsg_C           =       ' * Program is sacred to wonderful girl IRINIA V. YAROWAYA, died of 09.11.93 *';
  107.       asSacredMsg_D           =       ' * Åα«úαἼᠻ«ßó∩ΘÑ¡á »á¼∩Γ¿ êÉê좠ƒÉÄéÄë  (»«ú¿íΦÑ⌐  11.09.1993 ó î«ß¬óÑ) *';
  108.       asSacredMsg_E           =       ' ****************************************************************************';
  109.       asSacredMsg_F           =       ' * Your friends will always remember YOU, IRINA! Good, please help her now! *';
  110.       asSacredMsg_G           =       ' * Æó«¿ ñαπº∞∩ íπñπΓ »«¼¡¿Γ∞ ÆÑí∩, êÉêìÇ! â«ß»«ñ∞, »α«Φπ, »«¼«ú¿ Ñ⌐ ßÑ⌐τáß! *';
  111.       asSacredMsg_H           =       ' ****************************************************************************';
  112.       asSacredMsg_I           =       asProgramPrompt+' Press <ENTER> key to continue.';
  113.    {**** DON'T CHANGE THESE MESSAGES WITHOUT PRIOR WRITTEN PERMISSION!!! ****}
  114.  
  115.      { exit codes }
  116.        errTerminateOK           =     0;
  117.        errBootStrapDebug        =     1;
  118.        errBadReadFixedDisk      =     2;
  119.        errBadWriteFixedDisk     =     3;
  120.        errUserInstallAbort      =     4;
  121.        errUserWriteAbort        =     5;
  122.        errMismatchLoaderCode    =     6;
  123.        errBadNumeric            =     7;
  124.        errBadInitFixedDisk      =     8;
  125.        errFormatFailed          =     9;
  126.        errBadGetParmsFixedDisk  =     10;
  127.  
  128.     { miscellaneous }
  129.       asBlank                   =     '';
  130.       asSpaces10                =     '          ';
  131.       achHexPrefix              =     '$';
  132.       aSectorSize               =     512;
  133.       aSecSizeInWords           =     aSectorSize DIV 2;
  134.       aMaxTpStrLen              =     255;
  135.  
  136.       achZero                   =     '0';
  137.       achOne                    =     '1';
  138.       achTwo                    =     '2';
  139.       achThree                  =     '3';
  140.       achFour                   =     '4';
  141.       achFive                   =     '5';
  142.       achSix                    =     '6';
  143.       achSeven                  =     '7';
  144.       achEight                  =     '8';
  145.       achNine                   =     '9';
  146.  
  147.       achYes                    =     'Y';
  148.       achNo                     =     'N';
  149.  
  150.       achHardBoot               =     'H';
  151.       achFloppyBoot             =     'F';
  152.  
  153.       achAutoMode               =     'A';
  154.       achManualMode             =     'M';
  155.  
  156.       achCopyCmd                =     'C';
  157.       achDisplayCmd             =     'D';
  158.       achFormatCmd              =     'F';
  159.       achTestCmd                =     'T';
  160.       achSetCmd                 =     'S';
  161.  
  162.       aDefExt                   =     'BIN';
  163.       aDosExtMark               =     '.';
  164.       errOK                     =     0;
  165.  
  166.     { ASCII codes }
  167.       achNULL                   =     #00;
  168.       achLF                     =     #10;
  169.       achCR                     =     #13;
  170.  
  171.     { text messages }
  172.       asNotImplementedYet       =     'Not implemented yet.';
  173.  
  174.     {***** ATTENTION!!! Hard-coded values below. *****}
  175.     {***** Please modify carefully!              *****}
  176. {$IFDEF  DebugVersion}
  177.       adwBootSeg                =     $8000;     { segment at 512K }
  178. {$ELSE}
  179.       adwBootSeg                =     $0000;     { segment at 0K }
  180. {$ENDIF} {DebugVersion}
  181.      adwBootOfs                 =     $7C00;
  182.      adwABS0_Seg                =     $0000;
  183.      adwBiosMemSizeLoc          =     $413;
  184.      adwRelBootOfs              =     adwBootOfs + aSectorSize;
  185.      adwPartitionTable        =     $1BE;
  186.      aPartitonEntrySize         =     $10;
  187.      aMaxAvailLogicalPartition    =     4;
  188.      adwBootMarkOfs             =     adwPartitionTable + (aPartitonEntrySize*aMaxAvailLogicalPartition);
  189.      adwBootSecID               =     $AA55;
  190.  
  191.      aDebugOff                  =     0;
  192.      aDebugOn                   =     1;
  193.  
  194.      aBootPartitionID           =     $80;
  195.      aRetryOpCount              =     10;
  196.  
  197.      aFarJumpOpCode             =     $EA;      { iAPX86 opcodes }
  198.      aNearJumpOpCode            =     $E9;
  199.      aShortJumpOpCode           =     $EB;
  200.  
  201.      aRomVideoDriver            =     $10;      { IBM PC BIOS functions }
  202.      aRomDiskDriver             =     $13;
  203.      aRomKeyboardDriver         =     $16;
  204.      aRomBootDriver             =     $19;
  205.  
  206.      aBiosWaitKbdInput          =     $00;      { keyboard functions }
  207.  
  208.      btHeadsMoreThan8           =     $08;
  209.      aDefInterleaveFactor       =     $03;
  210.      aBadSectorFlag             =     $80;
  211.      aGoodSectorFlag            =     $00;
  212.      btSecNumMask               =     $3F;
  213.  
  214.      aHardDrive_0               =     $80;
  215.      aHardDrive_1               =     aHardDrive_0 + $1;
  216.  
  217.      aBiosSecCountIs1           =     $01;
  218.      aBiosSecNumIs1             =     $01;
  219.      aBiosHeadNumIs0            =     $00;
  220.      aBiosCylNumIs0             =     $00;
  221.  
  222.      aBiosResetOp               =     $00;      { disk functions }
  223.      aBiosReadOp                =     $02;
  224.      aBiosWriteOp               =     $03;
  225.      aBiosVerifyOp              =     $04;
  226.      aBiosFormatOp              =     $05;
  227.      aBiosGetDriveParmsOp       =     $08;
  228.      aBiosSetDriveParmsOp       =     $09;
  229.      aBiosTestIsDriveReady      =     $10;
  230.      aBiosRecalibrateDrive      =     $11;
  231.  
  232.      aHardDiskSupportNum        =     2;
  233.      aDiskParmTableSize         =     $10;                      {* Hard-Coded Values!!     *}
  234.      aDiskParmTableSizeDiv2     =     aDiskParmTableSize DIV 2;
  235.      aInitBitFlagsOfs           =     $1D;
  236.      aTotalSettingsSize         =     aDiskParmTableSize * aHardDiskSupportNum + 1;
  237.      aBootDiskDriveTableOfs     =     aInitBitFlagsOfs + 1;
  238.  
  239.  
  240.      aIntelVecSize              =     4;
  241.      aDrvParmVec_0              =     $41;
  242.      aDrvParmVec_1              =     $46;
  243.      aDrvParmVec_LowMemLoc_0    =     aDrvParmVec_0 * aIntelVecSize;
  244.      aDrvParmVec_LowMemLoc_1    =     aDrvParmVec_1 * aIntelVecSize;
  245.  
  246.  
  247.   {** ATTENTION!!! Use another memory locations if any problem occurred **}
  248.      aLowMemParmVecStoreArea_0  =     $C0 * aIntelVecSize;
  249.      aLowMemParmVecStoreArea_1  =     $C4 * aIntelVecSize;
  250.  
  251.   { copyright notice for detection of already installed copy }
  252.     asSearchNotice             =     'HD-MBoot 1993 D.Stefankov';
  253.  
  254.   { DOS partition magic values }
  255.     aDos12                     =      $01;
  256.     aDos16                     =      $04;
  257.     aDosBig                    =      $06;
  258.     aSecsPerFAT12              =      4096;
  259.     aSecsPerFAT16              =      65536;
  260.     aSecsPerFATBIG             =      $FFFFFFFF;
  261.  
  262.   { IBM magic values }
  263.     aPcTypeIsAT                =      $FC;
  264.     adwTestMemBufSeg           =      $8000;           { 512 K }
  265.     adwTestMemBufOfs           =      $0;
  266.  
  267.   { bit-mapped flags }
  268.     btFullMaskFF               =      $FF;
  269.     btSetDiskType_0            =      $01;
  270.     btSetDiskType_1            =      $02;
  271.     btReserved_02              =      $04;
  272.     btReserved_03              =      $08;
  273.     btReserved_04              =      $10;
  274.     btReserved_05              =      $20;
  275.     btReserved_06              =      $40;
  276.     btAskBootDisk              =      $80;
  277. {$IFDEF  PresentDiskDrive0}
  278.     btInitialDiskType_0        =      btSetDiskType_0;
  279. {$ELSE}
  280.     btInitialDiskType_0        =      $00;
  281. {$ENDIF} {PresentDiskDrive0}
  282. {$IFDEF  PresentDiskDrive1}
  283.     btInitialDiskType_1        =      btSetDiskType_1;
  284. {$ELSE}
  285.     btInitialDiskType_1        =      $00;
  286. {$ENDIF} {PresentDiskDrive1}
  287.     btInitialDiskTypes         =      btInitialDiskType_0 + btInitialDiskType_1;
  288.  
  289.  
  290. {*==================== TYPE DECLARATIONS PART ==========================*}
  291.  
  292. TYPE
  293.   {* strings *}
  294.        STR2                     =     STRING[2];
  295.        STR3                     =     STRING[3];
  296.        STR4                     =     STRING[4];
  297.        STR5                     =     STRING[5];
  298.        STR8                     =     STRING[8];
  299.  
  300.     {* Information about logical disk *}
  301.     recLogicalPartition  =  RECORD
  302.                  dbBootDriveMark              :       System.Byte;      {00}
  303.                  dbStartingHead               :       System.Byte;      {01}
  304.                  dwStartingCylSec             :       System.Word;      {02}
  305.                  dbOperatingSystemID          :       System.Byte;      {04}
  306.                  dbEndingHead                 :       System.Byte;      {05}
  307.                  dwEndingCylSec               :       System.Word;      {06}
  308.                  ddPrecedingSecs              :       System.Longint;   {08}
  309.                  ddSecsPerPartition           :       System.Longint;   {0C}
  310.                            END;
  311.     {* recLogicalPartition *}
  312.  
  313.     {* Master Boot Sector *}
  314.     recMasterBoot  =  RECORD
  315.          dbReservedCode           :  ARRAY[0..adwPartitionTable-1] OF System.Byte;              {000}
  316.          recDiskPartitionsTable   :  ARRAY[0..aMaxAvailLogicalPartition-1] OF recLogicalPartition;  {1BE}
  317.          dwValidBootRecID         :  System.Word;                                           {1FE}
  318.                            END;
  319.     {* recMasterBoot *}
  320.  
  321.  
  322.     {* Hard Disk Parameters Table *}
  323.     recHARD_DISK_PARMS    = RECORD
  324.         dwMAX_CYLS_NUM             :    System.Word;     {00}
  325.         dbMAX_HEADS_NUM             :    System.Byte;     {02}
  326.         dwSTART_WRC_XT             :    System.Word;     {03}
  327.         dwSTART_WRC                  :    System.Word;     {05}
  328.         dbMAX_ECC_DATA_BURST_LEN     :    System.Byte;     {07}
  329.         dbCONTROL_BYTE               :    System.Byte;     {08}
  330.         dbSTD_TIME_OUT_XT            :    System.Byte;     {09}
  331.         dbFMT_TIME_OUT_XT            :    System.Byte;     {0A}
  332.         dbCHECK_TIME_OUT_XT          :    System.Byte;     {0B}
  333.         dwLANDING_ZONE               :    System.Word;     {0C}
  334.         dbSECTORS_PER_TRACK          :    System.Byte;     {0E}
  335.         dbPARM_RESERVED              :    System.Byte;     {0F}
  336.                       END;
  337.     {* recHARD_DISK_PARMS *}
  338.  
  339.  
  340. {*====================== TYPED CONSTANTS PART ==========================*}
  341.  
  342. CONST
  343.    ddPrevIntVec41            :   System.Pointer         =       NIL;
  344.    ddPrevIntVec46            :   System.Pointer         =       NIL;
  345.    gbSetupParmsForDrive_0    :   System.Boolean         =       System.False;
  346.    gbSetupParmsForDrive_1    :   System.Boolean         =       System.False;
  347.  
  348.  
  349.  
  350. {*=========================== VARIABLES PART ===========================*}
  351.  
  352. VAR
  353.    grecFixedDiskBoot         :   recMasterBoot;
  354.    grecOrigFixedDiskBoot     :   recMasterBoot;
  355.    grecHARD_DISK_PARMS_0     :   recHARD_DISK_PARMS;
  356.    grecHARD_DISK_PARMS_1     :   recHARD_DISK_PARMS;
  357.    gfOutStream               :   FILE  OF  recMasterBoot;
  358.    gdbFormatSectorBuffer     :   ARRAY[0..aSectorSize-1]  OF  System.Byte;
  359.    gsTempInput               :   STRING;
  360.    gdwOurBootRecLen         :   System.Word;
  361.    gdwMemOfs                 :   System.Word;
  362.    gbUserAskExit             :   System.Boolean;
  363.    gbPCATFoundOk             :   System.Boolean;
  364.    gbOriginalMBRpresent      :   System.Boolean;
  365.  
  366.    gdbPcType                 :   System.Byte  ABSOLUTE  $F000:$FFFE;
  367.  
  368.  
  369.  
  370. {*=========================== PROCEDURAL PART ==========================*}
  371.  
  372.  
  373.  
  374. PROCEDURE _IPL_Code; near; assembler;
  375. {* Initial program loader. *}
  376. {* Note 1: This procedure must be always at beginning. *}
  377. {* Note 2: The length of code must be <= $1BE for non-debugging version. *}
  378. asm
  379. {$IFDEF  DebugVersion}
  380.         cmp      ax, aDebugOff        { Test for relocated code marker }
  381.         je       @InitCode
  382.  
  383.         mov      bx, cs               { Our Procedure in TP code segment }
  384.         mov      ds, bx               { We move it to new segment for debugging }
  385.         mov      ax, adwBootSeg
  386.         mov      es, ax
  387.         mov      cx, aSecSizeInWords
  388.         mov      si, 0
  389.         mov      di, adwBootOfs
  390.         push     es                   { Jump Segment into Stack }
  391.         push     di                   { Jump Offset  into Stack }
  392.         cld
  393.         rep      movsw
  394.  
  395.         mov      ax, aDebugOff        { we had relocated code }
  396.         retf                          { jump to relocated code }
  397.  
  398.   @InitCode:
  399. {$ENDIF} {DebugVersion}
  400.  
  401.         cli                           { disable ints during regs setup }
  402. {$IFDEF  DebugVersion}
  403.         mov      ax, adwBootSeg
  404. {$ELSE}
  405.     sub     ax, ax
  406. {$ENDIF} {DebugVersion}
  407.         mov      ds, ax               { set seg registers to zero = ABS0 seg }
  408.         mov      es, ax
  409.         mov      ss, ax               { stack at $0000:$7C00 }
  410.         mov      sp, adwBootOfs
  411.  
  412.         sti                           { re-enable interrupts }
  413.         cld                           { go forward }
  414.         mov      si, sp               { DS:SI -> 0:$7C00 }
  415.         mov      di, adwRelBootOfs    { ES:DI -> 0:$7E00 }
  416.         mov      cx, aSecSizeInWords  { words count }
  417.         rep      movsw                { relocate code to safe place }
  418.                       { jump to continue from new place }
  419.         db       aFarJumpOpCode       { Direct FAR Jump }
  420.     dw     adwRelBootOfs + (OFFSET @NewStart)
  421.     dw     adwBootSeg
  422.                                       { messages for user }
  423.                       { offset to ref        =>  $1D }
  424.   @bBitMappedFlags:
  425.         db       btInitialDiskTypes
  426.  
  427.   @ParametersTableForDrive_0:
  428.  {**       db       aDiskParmTableSize     DUP (0)  **}
  429. {$IFDEF  DriveType2}
  430.            dw       615
  431.            db       4
  432.            dw       0
  433.            dw       300
  434.            db       0
  435.            db       0
  436.            db       0
  437.            db       0
  438.            db       0
  439.            dw       615
  440.            db       17
  441.            db       0
  442. {$ELSE}
  443.            dw       0, 0, 0, 0
  444.            dw       0, 0, 0, 0
  445. {$ENDIF}  {DriveType2}
  446.  
  447.   @ParametersTableForDrive_1:
  448.  {**       db       aDiskParmTableSize     DUP (0)  **}
  449. {$IFDEF  DriveType2}
  450.            dw       615
  451.            db       4
  452.            dw       0
  453.            dw       300
  454.            db       0
  455.            db       0
  456.            db       0
  457.            db       0
  458.            db       0
  459.            dw       615
  460.            db       17
  461.            db       0
  462. {$ELSE}
  463.            dw       0, 0, 0, 0
  464.            dw       0, 0, 0, 0
  465. {$ENDIF}  {DriveType2}
  466.  
  467.  
  468.   @BootHello_MSG:
  469.         db       achCR,achLF
  470.         db       "HD-MBoot 1993 D.Stefankov"
  471.         db       achNULL
  472.  
  473.   @InitDriveType_0_MSG:
  474.     db     achCR, achLF
  475.         db       "<Init HD0>"
  476.         db       achNULL
  477.  
  478.   @InitDriveType_1_MSG:
  479.     db     achCR, achLF
  480.         db       "<Init HD1>"
  481.         db       achNULL
  482.  
  483.   @InitDriveFailed_MSG:
  484.     db     achCR, achLF
  485.         db       "<Bad Init>"
  486.         db       achNULL
  487.  
  488.   @ScanPartitionTable_MSG:
  489.     db     achCR, achLF
  490.         db       "<Scan Boot Table>"
  491.         db       achNULL
  492.  
  493.   @LoadOS_MSG:
  494.         db       achCR,achLF
  495.         db       '<Load OS>'
  496.         db       achCR,achLF
  497.         db       achNULL
  498.  
  499.   @BadPartition_MSG:
  500.         db       achCR,achLF
  501.         db       '<Bad Partition Table>'
  502.         db       achNULL
  503.  
  504.   @ErrLoadOS_MSG:
  505.         db       achCR,achLF
  506.         db       '<Error load OS>'
  507.         db       achNULL
  508.  
  509.   @BadOS_MSG:
  510.         db       achCR,achLF
  511.         db       '<Missing OS>'
  512.         db       achNULL
  513.  
  514.   @AskWhereBootFrom_MSG:
  515.         db       achCR,achLF
  516.         db       '<Boot (H/F)>'
  517.         db       achCR,achLF
  518.         db       achNULL
  519.  
  520.   @NewStart:
  521.         mov      si, OFFSET  @BootHello_MSG
  522.         call     @AsciizOutput        { Display string in format <ASCII+zero> }
  523.  
  524.  
  525.  @InitDriveParametersTable_0:
  526.         mov      di, aLowMemParmVecStoreArea_0
  527.         mov      dl, aHardDrive_0
  528.  
  529.         test     BYTE PTR  [(OFFSET @bBitMappedFlags)+adwRelBootOfs], btSetDiskType_0
  530.         jz      @InitDriveParametersTable_1
  531.  
  532.         mov      si, OFFSET  @InitDriveType_0_MSG
  533.         call     @AsciizOutput        { Display string in format <ASCII+zero> }
  534.  
  535.         mov      si, (OFFSET @ParametersTableForDrive_0) + adwRelBootOfs
  536.         mov      bx, aDrvParmVec_LowMemLoc_0
  537.         call     @InitDriveParm
  538.  
  539.  
  540.  @InitDriveParametersTable_1:
  541.         test      BYTE PTR [(OFFSET @bBitMappedFlags)+adwRelBootOfs], btSetDiskType_1
  542.         jz      @CheckAboutAsk
  543.  
  544.         mov      si, OFFSET  @InitDriveType_1_MSG
  545.         call     @AsciizOutput        { Display string in format <ASCII+zero> }
  546.  
  547.         mov      si, (OFFSET @ParametersTableForDrive_1) + adwRelBootOfs
  548.         mov      di, aLowMemParmVecStoreArea_1
  549.         mov      bx, aDrvParmVec_LowMemLoc_1
  550.         inc      dx
  551.         call     @InitDriveParm
  552.  
  553.  @CheckAboutAsk:
  554.         test     BYTE PTR [(OFFSET @bBitMappedFlags)+adwRelBootOfs], btAskBootDisk
  555.         jz      @LookBootTable
  556.  
  557.  @AskAgain:
  558.         mov      si, OFFSET  @AskWhereBootFrom_MSG
  559.         call     @AsciizOutput        { Display string in format <ASCII+zero> }
  560.         mov      ah, aBiosWaitKbdInput
  561.         int      aRomKeyboardDriver
  562.         and      al, 11011111B        { make uppercase }
  563.         cmp      al, achHardBoot
  564.         je      @LookBootTable
  565.         cmp      al, achFloppyBoot
  566.         jne     @AskAgain
  567.         int      aRomBootDriver
  568.  
  569.  @LookBootTable:
  570.         mov      si, OFFSET  @ScanPartitionTable_MSG
  571.         call     @AsciizOutput        { Display string in format <ASCII+zero> }
  572.  
  573.         mov      cx, aMaxAvailLogicalPartition
  574.         mov      si, adwRelBootOfs + adwPartitionTable - aPartitonEntrySize
  575.  
  576.  @IsBootablePartition:
  577.         add      si, aPartitonEntrySize
  578.         cmp      BYTE PTR [si], aBootPartitionID
  579.         je      @TryLoadOS
  580.  
  581.         dec      cx
  582.         jnz      @IsBootablePartition
  583.  
  584.   @BadPartition:                      { bad partition table }
  585.         mov      si, OFFSET  @BadPartition_MSG
  586.  
  587.   @BootStop:
  588.         call     @AsciizOutput        { Display string in format <ASCII+zero> }
  589.  
  590.   @StopCPU:
  591.         jmp      @StopCPU          { loop forever }
  592.  
  593.  @TryLoadOS:
  594.         mov      dx, [si]             { DH = head, DL = drive }
  595.         mov      cx, [si+2]           { CX = cyl/sec }
  596.  
  597.         mov      bx, adwBootOfs       { ES:BX -> buffer }
  598.         mov      bp, aRetryOpCount    { retry count }
  599.  
  600.   @TryLoad:
  601.        mov      ax, (aBiosReadOp SHL 8) + aBiosSecCountIs1
  602.                                       { read a sector from disk to memory }
  603.        int      aRomDiskDriver        { call ROM BIOS disk driver }
  604.        jnc      @SectorLoaded         { jump if driver says OK }
  605.        mov    ah, (aBiosResetOp)    { reset controller }
  606.        int    aRomDiskDriver          { call ROM BIOS disk driver }
  607.        dec      bp                    { decrement a retries counter }
  608.        jnz      @TryLoad
  609.  
  610.  @BadDisk:                             { may be disk bad? }
  611.        mov      si, OFFSET  @ErrLoadOS_MSG
  612.        jmp     @BootStop
  613.  
  614.  
  615.   @SectorLoaded:
  616.         mov    si, OFFSET  @BadOS_MSG  { non-bootable sector }
  617.         cmp     word ptr [bx+adwBootMarkOfs], adwBootSecID
  618.         jne    @BootStop
  619.  
  620.         push     es                   { indirect far jump }
  621.         push     bx
  622.  
  623.         mov      si, OFFSET  @LoadOS_MSG
  624.         call     @AsciizOutput        { Display string in format <ASCII+zero> }
  625.  
  626.         retf
  627.  
  628.  
  629.  {** _InitDriveParm  PROC NEAR **}
  630.   @InitDriveParm:
  631.         mov      [bx], di             { store a new vector }
  632.         mov      [bx+2], ds
  633.         mov      cx, aDiskParmTableSizeDiv2
  634.         rep      movsw
  635.         mov      ah, aBiosSetDriveParmsOp
  636.         int     aRomDiskDriver          { call ROM BIOS disk driver }
  637.         jnc     @Done
  638.  
  639.   @InitFailed:
  640.        mov      si, OFFSET  @InitDriveFailed_MSG
  641.        jmp     @BootStop
  642.  
  643.  {** _InitDriveParmENDP  **}
  644.  
  645.  
  646.  {** _AsciizOutput  PROC NEAR **}
  647.   @AsciizOutput:
  648.         add    si, adwRelBootOfs      { fix problem with relocation }
  649.  
  650.   @NextChar:
  651.         lodsb                         { get char }
  652.         or       al, al               { AL is zero? }
  653.         jz       @Done                { exit if match }
  654.         mov      bx, 0007h            { white-on-black }
  655.         mov      ah, 0Eh              { TTY function }
  656.         int      aRomVideoDriver      { call ROM BIOS video driver }
  657.         jmp      @NextChar
  658.  
  659.   @Done:
  660.         {retn}                        { return to caller }
  661.                                       {! Generates automatically by TP!}
  662.  {** _AsciizOutput  ENDP  **}
  663.  
  664. END; {end-asm}
  665. { _IPL_Code }
  666.  
  667.  
  668.  
  669. {**** procedural part 1 ****}
  670.  
  671. PROCEDURE    _DummyProc; near; assembler;
  672. {* It is used for reference only. Don't remove this code!!! *}
  673. {reserved space = 128 bytes}
  674. asm
  675.    DB  achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL
  676.    DB  achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL
  677.    DB  achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL
  678.    DB  achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL
  679.    DB  achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL
  680.    DB  achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL
  681.    DB  achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL
  682.    DB  achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL
  683.    DB  achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL
  684.    DB  achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL
  685.    DB  achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL
  686.    DB  achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL
  687.    DB  achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL
  688.    DB  achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL
  689.    DB  achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL
  690.    DB  achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL, achNULL
  691. END;
  692. { _DummyProc }
  693.  
  694.  
  695.  
  696. {*=========================== FUNCTIONAL PART ==========================*}
  697.  
  698.  
  699. FUNCTION  _fnddDoBiosCylSecNum(dwCyl,dwSec : System.Word) : System.Longint;
  700. {* Construct a BIOS compatible cyl/sec pair. *}
  701. BEGIN
  702.    _fnddDoBiosCylSecNum := ((dwCyl AND $FF) SHL 8) +
  703.                            ((dwCyl AND $0300) SHR 2) +
  704.                            (dwSec AND $3F);
  705. END;
  706. { _fnddDoBiosCylSecNum }
  707.  
  708.  
  709. FUNCTION  _fnsForceFileExtension(sFileName, sDefExt : STRING) : STRING;
  710. {* Add extension for filename if not present. *}
  711. BEGIN
  712.    IF (System.Pos(aDosExtMark,sFileName) = 0)
  713.      THEN sFileName := sFileName + aDosExtMark + sDefExt;
  714.    {if-then}
  715.   _fnsForceFileExtension := sFileName;
  716. END;
  717. { _fnsForceFileExtension }
  718.  
  719.  
  720. FUNCTION   _fnchGetFirstChar(sInput : STRING) : System.Char;
  721. {* Returns a first char from string. *}
  722. VAR
  723.   chTemp  :  System.Char;
  724.  
  725. BEGIN
  726.    IF (System.Length(sInput) <> 0)
  727.      THEN  chTemp := sInput[1]
  728.      ELSE  chTemp := System.Char(achNULL);
  729.    {if-then-else}
  730.   _fnchGetFirstChar := chTemp;
  731. END;
  732. { _fnchGetFirstChar }
  733.  
  734.  
  735. FUNCTION  _fndwGetValue(sInput : STRING)  : System.Word;
  736. {* Translates string to its numeric representation. *}
  737. VAR
  738.   iErrorCode   :  System.Integer;
  739.   dwTempValue  :  System.Word;
  740.  
  741. BEGIN
  742.    System.Val(sInput,dwTempValue,iErrorCode);
  743.    IF (iErrorCode <> 0)
  744.       THEN  BEGIN
  745.          System.WriteLn(asProgramPrompt+' Bad numeric value.');
  746.          System.Halt(errBadNumeric);
  747.              END;
  748.    {if-then}
  749.  
  750.   _fndwGetValue := dwTempValue;
  751. END;
  752. { _fndwGetValue }
  753.  
  754.  
  755. FUNCTION  _fnsNumToStr(dwNum,dwWidth : System.Word) : STRING;
  756. {* Convert a numeric value to its string representation. *}
  757. VAR
  758.   sTemp : STRING;
  759.  
  760. BEGIN
  761.    System.Str(dwNum:dwWidth,sTemp);
  762.   _fnsNumToStr := sTemp;
  763. END;
  764. { _fnsNumToStr }
  765.  
  766.  
  767. FUNCTION  _fnsNumToStr3(dwNum : System.Word) : STR3;
  768. {* Convert a numeric value to its string representation. *}
  769. VAR
  770.   sTemp : STR3;
  771.  
  772. BEGIN
  773.    System.Str(dwNum:3,sTemp);
  774.   _fnsNumToStr3 := sTemp;
  775. END;
  776. { _fnsNumToStr3 }
  777.  
  778.  
  779. FUNCTION  _fnsNumToStr4(dwNum : System.Word) : STR4;
  780. {* Convert a numeric value to its string representation. *}
  781. VAR
  782.   sTemp : STR4;
  783.  
  784. BEGIN
  785.    System.Str(dwNum:4,sTemp);
  786.   _fnsNumToStr4 := sTemp;
  787. END;
  788. { _fnsNumToStr4 }
  789.  
  790.  
  791. FUNCTION  _fnsNumToStr5(dwNum : System.Word) : STR5;
  792. {* Convert a numeric value to its string representation. *}
  793. VAR
  794.   sTemp : STR5;
  795.  
  796. BEGIN
  797.    System.Str(dwNum:5,sTemp);
  798.   _fnsNumToStr5 := sTemp;
  799. END;
  800. { _fnsNumToStr5 }
  801.  
  802.  
  803.  
  804.  
  805. {*=========================== PROCEDURAL PART ==========================*}
  806.  
  807. PROCEDURE    _CopyrightDisplay;
  808. {* Outputs the copyright notice. *}
  809. BEGIN
  810.  
  811.    {**** Removing of these messages is strictly inhibited!! ****}
  812.      System.WriteLn;
  813.      System.WriteLn(asSacredMsg_A);
  814.      System.WriteLn(asSacredMsg_B);
  815.      System.WriteLn(asSacredMsg_C);
  816.      System.WriteLn(asSacredMsg_D);
  817.      System.WriteLn(asSacredMsg_E);
  818.      System.WriteLn(asSacredMsg_F);
  819.      System.WriteLn(asSacredMsg_G);
  820.      System.WriteLn(asSacredMsg_H);
  821.      System.WriteLn(asSacredMsg_I);
  822.      System.ReadLn;
  823.    {**** Removing of these messages is strictly inhibited!! ****}
  824.  
  825.      System.WriteLn(asPurpose+
  826.                     '  Version '+
  827.                     asVersion+
  828.                     ',  '+
  829.                     asCopyright+
  830.                     '  '+
  831.                     asAuthor);
  832. END;  { _CopyrightDisplay }
  833.  
  834.  
  835. PROCEDURE  _GetDiskDriveParameters(dbDriveNum : System.Byte);
  836. {* Gets the user defined parameters for disk drive. *}
  837. VAR
  838.    recDriveParms   :   recHARD_DISK_PARMS;
  839.    sTemp           :   STRING;
  840.    bAutoMode       :   System.Boolean;
  841.  
  842. BEGIN
  843.      System.Write(asProgramPrompt+'Enter parameters hard drive ',dbDriveNum,': (Y/N): ');
  844.      System.ReadLn(sTemp);
  845.      IF  (System.UpCase(_fnchGetFirstChar(sTemp)) <> achNo)
  846.        THEN  BEGIN
  847.           System.Move(System.Mem[System.Seg(_IPL_Code):
  848.                         (aBootDiskDriveTableOfs+(aDiskParmTableSize*dbDriveNum))],
  849.                       recDriveParms,
  850.                       aDiskParmTableSize);
  851.  
  852.           System.Write(asProgramPrompt+'Select mode to enter data (A=auto,M=manual)? (A/M): ');
  853.           System.ReadLn(sTemp);
  854.           bAutoMode := System.True;
  855.  
  856.           IF  (System.UpCase(_fnchGetFirstChar(sTemp)) = achManualMode)
  857.             THEN  bAutoMode := System.False;
  858.           {if-then}
  859.  
  860.           WITH  recDriveParms  DO
  861.           BEGIN
  862.              System.Write(asProgramPrompt+'Number of cylinders (CR=',dwMAX_CYLS_NUM,'): ');
  863.              System.ReadLn(sTemp);
  864.              IF (sTemp <> asBlank)
  865.                THEN  dwMAX_CYLS_NUM := _fndwGetValue(sTemp);
  866.              {if-then}
  867.              System.Write(asProgramPrompt+'Number of heads (CR=',dbMAX_HEADS_NUM,'): ');
  868.              System.ReadLn(sTemp);
  869.              IF (sTemp <> asBlank)
  870.                THEN  dbMAX_HEADS_NUM := System.Lo(_fndwGetValue(sTemp));
  871.              {if-then}
  872.              IF (dbMAX_HEADS_NUM > btHeadsMoreThan8)
  873.                  THEN  dbCONTROL_BYTE := dbCONTROL_BYTE OR btHeadsMoreThan8;
  874.              {if-then}
  875.              IF (bAutoMode)
  876.               THEN  {empty}
  877.               ELSE  BEGIN
  878.                  System.Write(asProgramPrompt+'Starting write-precompensation cylinder for XT (CR=',dwSTART_WRC_XT,'): ');
  879.                  System.ReadLn(sTemp);
  880.                  IF (sTemp <> asBlank)
  881.                    THEN  dwSTART_WRC_XT := _fndwGetValue(sTemp);
  882.                  {if-then}
  883.                    END;
  884.              {if-then}
  885.              System.Write(asProgramPrompt+'Starting write-precompensation cylinder (CR=',dwSTART_WRC,'): ');
  886.              System.ReadLn(sTemp);
  887.              IF (sTemp <> asBlank)
  888.                THEN  dwSTART_WRC := _fndwGetValue(sTemp);
  889.              {if-then}
  890.              IF (bAutoMode)
  891.               THEN  {empty}
  892.               ELSE  BEGIN
  893.                  System.Write(asProgramPrompt+'ECC data burst length (CR=',dbMAX_ECC_DATA_BURST_LEN,'): ');
  894.                  System.ReadLn(sTemp);
  895.                  IF (sTemp <> asBlank)
  896.                    THEN  dbMAX_ECC_DATA_BURST_LEN := System.Lo(_fndwGetValue(sTemp));
  897.                  {if-then}
  898.                  System.Write(asProgramPrompt+'Control Byte (CR=',dbCONTROL_BYTE,'): ');
  899.                  System.ReadLn(sTemp);
  900.                  IF (sTemp <> asBlank)
  901.                    THEN  dbCONTROL_BYTE := System.Lo(_fndwGetValue(sTemp));
  902.                  {if-then}
  903.                  System.Write(asProgramPrompt+'Standard time-out for XT (CR=',dbSTD_TIME_OUT_XT,'): ');
  904.                  System.ReadLn(sTemp);
  905.                  IF (sTemp <> asBlank)
  906.                    THEN  dbSTD_TIME_OUT_XT := System.Lo(_fndwGetValue(sTemp));
  907.                  {if-then}
  908.                  System.Write(asProgramPrompt+'Format time-out for XT (CR=',dbFMT_TIME_OUT_XT,'): ');
  909.                  System.ReadLn(sTemp);
  910.                  IF (sTemp <> asBlank)
  911.                    THEN  dbFMT_TIME_OUT_XT := System.Lo(_fndwGetValue(sTemp));
  912.                  {if-then}
  913.                  System.Write(asProgramPrompt+'Check time-out for XT (CR=',dbCHECK_TIME_OUT_XT,'): ');
  914.                  System.ReadLn(sTemp);
  915.                  IF (sTemp <> asBlank)
  916.                    THEN  dbCHECK_TIME_OUT_XT := System.Lo(_fndwGetValue(sTemp));
  917.                  {if-then}
  918.                    END;
  919.              {if-then}
  920.              System.Write(asProgramPrompt+'Landing zone (CR=',dwLANDING_ZONE,'): ');
  921.              System.ReadLn(sTemp);
  922.              IF (sTemp <> asBlank)
  923.                THEN  dwLANDING_ZONE := _fndwGetValue(sTemp);
  924.              {if-then}
  925.              System.Write(asProgramPrompt+'Number of sectors/track (CR=',dbSECTORS_PER_TRACK,'): ');
  926.              System.ReadLn(sTemp);
  927.              IF (sTemp <> asBlank)
  928.                THEN  dbSECTORS_PER_TRACK := System.Lo(_fndwGetValue(sTemp));
  929.              {if-then}
  930.              IF (bAutoMode)
  931.               THEN  {empty}
  932.               ELSE  BEGIN
  933.                  System.Write(asProgramPrompt+'Reserved byte (CR=',dbPARM_RESERVED,'): ');
  934.                  System.ReadLn(sTemp);
  935.                  IF (sTemp <> asBlank)
  936.                    THEN  dbPARM_RESERVED := System.Lo(_fndwGetValue(sTemp));
  937.                  {if-then}
  938.                    END;
  939.              {if-then}
  940.           END;
  941.           {with-do}
  942.  
  943.           WITH  recDriveParms  DO
  944.           BEGIN
  945.              System.WriteLn(asProgramPrompt+'===== User defined parameters for fixed disk ',
  946.                             dbDriveNum,' ===== ');
  947.              System.WriteLn(asProgramPrompt+'Number of cylinders = ',dwMAX_CYLS_NUM);
  948.              System.WriteLn(asProgramPrompt+'Number of heads = ',dbMAX_HEADS_NUM);
  949.              System.WriteLn(asProgramPrompt+'Starting write-precompensation cylinder for XT = ',dwSTART_WRC_XT);
  950.              System.WriteLn(asProgramPrompt+'Starting write-precompensation cylinder = ',dwSTART_WRC);
  951.              System.WriteLn(asProgramPrompt+'ECC data burst length = ',dbMAX_ECC_DATA_BURST_LEN);
  952.              System.WriteLn(asProgramPrompt+'Control Byte = ',dbCONTROL_BYTE);
  953.              System.WriteLn(asProgramPrompt+'Standard time-out for XT = ',dbSTD_TIME_OUT_XT);
  954.              System.WriteLn(asProgramPrompt+'Format time-out for XT = ',dbFMT_TIME_OUT_XT);
  955.              System.WriteLn(asProgramPrompt+'Check time-out for XT = ',dbCHECK_TIME_OUT_XT);
  956.              System.WriteLn(asProgramPrompt+'Landing zone = ',dwLANDING_ZONE);
  957.              System.WriteLn(asProgramPrompt+'Number of sectors/track = ',dbSECTORS_PER_TRACK);
  958.              System.WriteLn(asProgramPrompt+'Reserved byte = ',dbPARM_RESERVED);
  959.           END;
  960.           {with-do}
  961.  
  962.           System.Write(asProgramPrompt+'All entered data correct? (N/Y): ');
  963.           System.ReadLn(sTemp);
  964.           IF  (System.UpCase(_fnchGetFirstChar(sTemp)) = achYes)
  965.             THEN  BEGIN
  966.              System.WriteLn(asProgramPrompt+'User data for drive ',dbDriveNum,' accepted.');
  967.              System.Move(recDriveParms,
  968.                          System.Mem[System.Seg(_IPL_Code):
  969.                                 (aBootDiskDriveTableOfs+(aDiskParmTableSize*dbDriveNum))],
  970.                           aDiskParmTableSize);
  971.                    END
  972.             ELSE   BEGIN
  973.              System.WriteLn(asProgramPrompt+'No accepted user data for drive ',dbDriveNum,'.');
  974.                    END;
  975.           {if-then-else}
  976.              END;
  977.      {if-then}
  978. END;
  979. { _GetDiskDriveParameters }
  980.  
  981.  
  982. PROCEDURE  _AttachOrDeAttachDrive(dbDriveNum : System.Byte);
  983. {* Enable/disable drive type setting at boot time. *}
  984. VAR
  985.    dbDriveMask  :  System.Byte;
  986.  
  987. BEGIN
  988.     dbDriveMask := System.Mem[System.Seg(_IPL_Code):aInitBitFlagsOfs];
  989.     IF ((dbDriveMask AND (1 SHL dbDriveNum)) = 0)
  990.       THEN  BEGIN
  991.         System.WriteLn(asProgramPrompt+'Drive ',dbDriveNum,' was inactive. Now active.');
  992.             END
  993.       ELSE  BEGIN
  994.         System.WriteLn(asProgramPrompt+'Drive ',dbDriveNum,' was active. Now inactive.');
  995.             END;
  996.     {if-then-else}
  997.     System.Mem[System.Seg(_IPL_Code):(aInitBitFlagsOfs)] := dbDriveMask XOR (1 SHL dbDriveNum);
  998. END;
  999. { _AttachOrDeAttachDrive }
  1000.  
  1001.  
  1002. PROCEDURE  _ToggleBootDriveAsk;
  1003. {* Enable/disable drive type setting at boot time. *}
  1004. VAR
  1005.    dbAskBootDrive  :  System.Byte;
  1006.  
  1007. BEGIN
  1008.     dbAskBootDrive := System.Mem[System.Seg(_IPL_Code):(aInitBitFlagsOfs)];
  1009.     IF ((dbAskBootDrive AND System.Byte(btAskBootDisk)) <> 0)
  1010.       THEN  BEGIN
  1011.         System.WriteLn(asProgramPrompt+'Boot drive prompt was active. Now inactive.');
  1012.             END
  1013.       ELSE  BEGIN
  1014.         System.WriteLn(asProgramPrompt+'Boot drive prompt was inactive. Now active.');
  1015.             END;
  1016.     {if-then-else}
  1017.     dbAskBootDrive := dbAskBootDrive XOR btAskBootDisk;
  1018.     System.Mem[System.Seg(_IPL_Code):(aInitBitFlagsOfs)] := dbAskBootDrive;
  1019. END;
  1020. { _ToggleBootDriveAsk }
  1021.  
  1022.  
  1023. PROCEDURE  _SaveMBRtoFile;
  1024. {* Write a Master Boot Record to File. *}
  1025. VAR
  1026.    sTempInput  :  STRING;
  1027.  
  1028. BEGIN
  1029.       System.Write(asProgramPrompt+'Write MBR to file (Y/N): ');
  1030.       System.ReadLn(sTempInput);
  1031.  
  1032.       IF  (System.UpCase(_fnchGetFirstChar(sTempInput)) <> achNo)
  1033.          THEN  BEGIN
  1034.            System.Write(asProgramPrompt+'Enter filename (def.ext.='+aDefExt+'): ');
  1035.            System.ReadLn(sTempInput);
  1036.  
  1037.            IF (sTempInput <> asBlank)
  1038.               THEN  BEGIN
  1039.                 sTempInput := _fnsForceFileExtension(sTempInput,aDefExt);
  1040.                 System.WriteLn(asProgramPrompt+'Copy MBR to file.');
  1041.               {** no check for errors! **}
  1042.                 System.Assign(gfOutStream,sTempInput);
  1043.                 {$I-}
  1044.                 System.Rewrite(gfOutStream);
  1045.                 {$I+}
  1046.                 IF (System.IoResult <> errOK)
  1047.                   THEN  BEGIN
  1048.                      System.WriteLn(asProgramPrompt+'Unable to create output file.');
  1049.                         END
  1050.                    ELSE  BEGIN
  1051.                      System.Write(gfOutStream,grecFixedDiskBoot);
  1052.                      System.Close(gfOutStream);
  1053.                          END;
  1054.                 {if-then-else}
  1055.                     END;
  1056.           {if-then}
  1057.                END;
  1058.  
  1059.       {if-then}
  1060. END;
  1061. { _SaveMBRtoFile }
  1062.  
  1063.  
  1064. PROCEDURE  _CopyLoaderCodeToMBR;
  1065. {* Copy boot loader code to MBR buffer. *}
  1066. BEGIN
  1067.    System.WriteLn(asProgramPrompt+'Copy loader code to MBR buffer.');
  1068.    System.Move(System.Mem[System.Seg(_IPL_Code):0],
  1069.                grecFixedDiskBoot,
  1070.                gdwOurBootRecLen);
  1071. END;
  1072. { _CopyLoaderCodeToMBR }
  1073.  
  1074.  
  1075. PROCEDURE   _WriteMBRtoFixedDisk;
  1076. {* Write a Master Boot Record to fixed disk. *}
  1077. VAR
  1078.    bStatusOk  :  System.Boolean;
  1079.  
  1080. BEGIN
  1081.    System.WriteLn(asProgramPrompt+'Writing of MBR to fixed disk 0.');
  1082.    bStatusOk := System.True;
  1083.  { make sure that bootable sector is present }
  1084.    grecFixedDiskBoot.dwValidBootRecID := adwBootSecID;
  1085.    asm
  1086.          mov     dx, (aBiosHeadNumIs0 SHL 8) + aHardDrive_0
  1087.          mov     cx, (aBiosCylNumIs0 SHL 8) + aBiosSecNumIs1
  1088.          mov     ax, ds
  1089.          mov     es, ax                { ES = Turbo DS }
  1090.          mov     bx, OFFSET grecFixedDiskBoot
  1091.          mov     ax, (aBiosWriteOp SHL 8) + aBiosSecCountIs1
  1092.          int     aRomDiskDriver        { ROM BIOS disk driver }
  1093.          jnc     @Done
  1094.          { we know that writing failed here }
  1095.          mov     bStatusOk, System.False
  1096.       @Done:
  1097.    END;
  1098.    {asm-end}
  1099.  
  1100.    IF NOT(bStatusOk)
  1101.       THEN  BEGIN
  1102.          System.WriteLn(asProgramPrompt+'Unable to write MBR to fixed disk.');
  1103.          System.Halt(errBadWriteFixedDisk);
  1104.             END;
  1105.    {if-then}
  1106. END;
  1107. { _WriteMBRtoFixedDisk }
  1108.  
  1109.  
  1110. PROCEDURE   _ReadMBRfromFixedDisk;
  1111. {* Read a Master Boot Record from a fixed disk. *}
  1112. VAR
  1113.    bStatusOk  :  System.Boolean;
  1114.  
  1115. BEGIN
  1116.     System.WriteLn(asProgramPrompt+'Reading of MBR from fixed disk.');
  1117.  
  1118.     bStatusOk := System.True;
  1119.     asm
  1120.         mov     dx, (aBiosHeadNumIs0 SHL 8) + aHardDrive_0
  1121.         mov     cx, (aBiosCylNumIs0 SHL 8) + aBiosSecNumIs1
  1122.         mov     ax, ds
  1123.         mov     es, ax                { ES = Turbo DS }
  1124.         mov     bx, OFFSET grecFixedDiskBoot
  1125.         mov     ax, (aBiosReadOp SHL 8) + aBiosSecCountIs1
  1126.         int     aRomDiskDriver        { ROM BIOS disk driver }
  1127.         jnc     @Done
  1128.                                       { at this point reading failed }
  1129.         mov     bStatusOk, System.False
  1130.  
  1131.      @Done:
  1132.     END;
  1133.     {asm-end}
  1134.  
  1135.   IF NOT(bStatusOk)
  1136.     THEN  BEGIN
  1137.        System.WriteLn(asProgramPrompt+'Unable to read MBR from fixed disk.');
  1138.        System.Halt(errBadReadFixedDisk);
  1139.           END;
  1140.   {if-then}
  1141. END;
  1142. { _ReadMBRfromFixedDisk }
  1143.  
  1144.  
  1145. PROCEDURE  _CopyDriveTypesAndSettingsFromMBR;
  1146. {* Copy boot loader code to MBR buffer. *}
  1147. BEGIN
  1148.    System.WriteLn(asProgramPrompt+'Copy drive settings/types to new loader code.');
  1149.    System.Move(System.Mem[System.Seg(grecFixedDiskBoot):(System.Ofs(grecFixedDiskBoot)+aInitBitFlagsOfs)],
  1150.                System.Mem[System.Seg(_IPL_Code):aInitBitFlagsOfs],
  1151.                aTotalSettingsSize);
  1152. END;
  1153. { _CopyDriveTypesAndSettingsFromMBR }
  1154.  
  1155.  
  1156. PROCEDURE  _CopyDiskParmsFromIPLforFixedDisk(VAR recHD_Parms: recHARD_DISK_PARMS; dbDriveNum : System.Byte);
  1157. {* Extract drive 0 parameters. *}
  1158. BEGIN
  1159.     System.Move(System.Mem[System.Seg(_IPL_Code):
  1160.                  (aBootDiskDriveTableOfs+(aDiskParmTableSize*dbDriveNum))],
  1161.                 recHD_Parms,
  1162.                 aDiskParmTableSize);
  1163. END;
  1164. { _CopyDiskParmsFromIPLforFixedDisk }
  1165.  
  1166.  
  1167. PROCEDURE  _RestoreMBRfromFile;
  1168. {* Recover an original boot record *}
  1169. VAR
  1170.    sTempInput  :  STRING;
  1171.  
  1172. BEGIN
  1173.    System.Write(asProgramPrompt+'Restore old MBR (Y/N): ');
  1174.    System.ReadLn(sTempInput);
  1175.  
  1176.    IF  (System.UpCase(_fnchGetFirstChar(sTempInput)) <> achNo)
  1177.       THEN  BEGIN
  1178.         System.Write(asProgramPrompt+'Enter filename (def.ext.='+aDefExt+'): ');
  1179.         System.ReadLn(sTempInput);
  1180.         IF (sTempInput <> asBlank)
  1181.            THEN  BEGIN
  1182.              sTempInput := _fnsForceFileExtension(sTempInput,aDefExt);
  1183.              System.WriteLn(asProgramPrompt+'Read original MBR from file.');
  1184.  
  1185.              {** no check for errors **}
  1186.              System.Assign(gfOutStream,sTempInput);
  1187.              {$I-}
  1188.              System.Reset(gfOutStream);
  1189.              {$I+}
  1190.              IF (System.IoResult <> errOK)
  1191.                THEN  BEGIN
  1192.                   System.WriteLn(asProgramPrompt+'Unable to open input file.');
  1193.                      END
  1194.                ELSE  BEGIN
  1195.                   System.Read(gfOutStream,grecFixedDiskBoot);
  1196.                   System.Close(gfOutStream);
  1197.  
  1198.                    {* Write a new master boot record *}
  1199.                    _WriteMBRtoFixedDisk;
  1200.                      END;
  1201.              {if-then-else}
  1202.                  END;
  1203.         {if-then}
  1204.             END;
  1205.    {if-then}
  1206. END;
  1207. { _RestoreMBRfromFile }
  1208.  
  1209.  
  1210. PROCEDURE  _GetDriveParmsUsingBiosCall(dbDriveNum : System.Byte;
  1211.                                        VAR  dbErrorCode  :  System.Byte;
  1212.                                        VAR  dwMaxCylNum  :  System.Word;
  1213.                                        VAR  dbMaxHeadNum :  System.Byte;
  1214.                                        VAR  dbMaxSecsNum :  System.Byte);
  1215. {* Make a BIOS call to get a current drive parameters. *}
  1216. VAR
  1217.    bStatusOk  :  System.Boolean;
  1218.  
  1219. BEGIN
  1220.    System.WriteLn(asProgramPrompt+'Get disk drive ',dbDriveNum,' parameters.');
  1221.    bStatusOk := System.True;
  1222.    dbErrorCode := errOK;
  1223.    asm
  1224.        mov     dl, aHardDrive_0
  1225.        add     dl, dbDriveNum
  1226.        mov     ah, (aBiosGetDriveParmsOp)
  1227.        int     aRomDiskDriver        { ROM BIOS disk driver }
  1228.  
  1229.        jnc     @Done
  1230.            { we know that operation failed here }
  1231.        mov     bStatusOk, System.False
  1232.        les     di, dbErrorCode
  1233.        mov     es:[di], ah
  1234.     @Done:
  1235.        mov     ax, cx
  1236.        and     al, btSecNumMask
  1237.        les     di, dbMaxSecsNum
  1238.        mov     es:[di], al
  1239.        les     di, dwMaxCylNum
  1240.        and     cl, (btFullMaskFF - btSecNumMask)
  1241.        rol     cl, 1
  1242.        rol     cl, 1
  1243.        xchg    ch, cl
  1244.        mov     es:[di], cx
  1245.        les     di, dbMaxHeadNum
  1246.        mov     es:[di], dh
  1247.    END;
  1248.    {asm-end}
  1249.  
  1250. END;
  1251. { _GetDriveParmsUsingBiosCall }
  1252.  
  1253.  
  1254.  
  1255. PROCEDURE   _InitMasterPartitionRecord;
  1256. {* *}
  1257. VAR
  1258.    liLogicalSectorsPerDrive   :  System.Longint;
  1259.    sTempInput                 :  STRING;
  1260.    dwMaxCylNum                :  System.Word;
  1261.    dbMaxHead,
  1262.    dbMaxSecNum,
  1263.    dbDriveNum,
  1264.    dbErrorCode,
  1265.    dbOS_ID                    :  System.Byte;
  1266.  
  1267. BEGIN
  1268.    {* copy a disk parameters *}
  1269.       dbDriveNum := aHardDrive_0-aHardDrive_0;
  1270.      _GetDriveParmsUsingBiosCall(dbDriveNum,dbErrorCode,dwMaxCylNum,dbMaxHead,dbMaxSecNum);
  1271.  
  1272.     IF (dbErrorCode <> errOK)
  1273.        THEN  BEGIN
  1274.           System.WriteLn(asProgramPrompt+'Unable to get parameters for fixed disk ',dbDriveNum,'.');
  1275.           System.Halt(errBadGetParmsFixedDisk);
  1276.        END;
  1277.     {if-then}
  1278.  
  1279.     System.Write(asProgramPrompt+'Wipe all entries in partition table? (N/Y): ');
  1280.     System.ReadLn(sTempInput);
  1281.     IF  (System.UpCase(_fnchGetFirstChar(sTempInput)) = achYes)
  1282.        THEN  BEGIN
  1283.           System.WriteLn(asProgramPrompt+'Invalidates all entries in partition table.');
  1284.           System.FillChar(grecFixedDiskBoot.recDiskPartitionsTable[0],
  1285.                           aPartitonEntrySize*aMaxAvailLogicalPartition,
  1286.                           achNull);
  1287.              END;
  1288.     {if-then}
  1289.  
  1290.     System.Write(asProgramPrompt+'Select mode to enter data (A=auto,M=manual)? (A/M): ');
  1291.     System.ReadLn(sTempInput);
  1292.  
  1293.     IF  (System.UpCase(_fnchGetFirstChar(sTempInput)) = achManualMode)
  1294.        THEN  BEGIN
  1295.            System.WriteLn(asProgramPrompt+asNotImplementedYet);
  1296.              END
  1297.        ELSE  BEGIN
  1298.           WITH  recLogicalPartition(grecFixedDiskBoot.recDiskPartitionsTable[0])  DO
  1299.           BEGIN
  1300.              liLogicalSectorsPerDrive := System.Longint(dwMaxCylNum+1) * (dbMaxHead+1) * (dbMaxSecNum);
  1301.              dbBootDriveMark := aHardDrive_0;
  1302.              dbStartingHead  :=  aBiosHeadNumIs0+1;
  1303.              dwStartingCylSec := _fnddDoBiosCylSecNum(aBiosCylNumIs0,aBiosSecNumIs1);
  1304.  
  1305.              dbOS_ID := aDosBig;
  1306.              IF  (liLogicalSectorsPerDrive < aSecsPerFAT16)
  1307.                 THEN  dbOS_ID := aDos16;
  1308.              {if-then}
  1309.              IF  (liLogicalSectorsPerDrive < aSecsPerFAT12)
  1310.                 THEN  dbOS_ID := aDos12;
  1311.              {if-then}
  1312.              dbOperatingSystemID := dbOS_ID;
  1313.  
  1314.              dbEndingHead := dbMaxHead;
  1315.              dwEndingCylSec := _fnddDoBiosCylSecNum((dwMaxCylNum),dbMaxSecNum);
  1316.              ddPrecedingSecs := dbMaxSecNum;
  1317.              ddSecsPerPartition := liLogicalSectorsPerDrive - ddPrecedingSecs;
  1318.           END;
  1319.           {with-do}
  1320.              END;
  1321.     {if-then-else}
  1322. END;
  1323. { _InitMasterPartitionRecord }
  1324.  
  1325.  
  1326. PROCEDURE  _DoBiosCmdForSetDriveParms(dbDriveNum : System.Byte);
  1327. {* Make a BIOS call to set a new drive parameters. *}
  1328. VAR
  1329.    bStatusOk  :  System.Boolean;
  1330.  
  1331. BEGIN
  1332.    System.WriteLn(asProgramPrompt+'Set disk drive ',dbDriveNum,' parameters.');
  1333.    bStatusOk := System.True;
  1334.    asm
  1335.        mov     dl, aHardDrive_0
  1336.        add     dl, dbDriveNum
  1337.        mov     ah, (aBiosResetOp)
  1338.        int     aRomDiskDriver        { ROM BIOS disk driver }
  1339.  
  1340.        mov     dl, aHardDrive_0
  1341.        add     dl, dbDriveNum
  1342.        mov     ah, (aBiosSetDriveParmsOp)
  1343.        int     aRomDiskDriver        { ROM BIOS disk driver }
  1344.        jnc     @Done
  1345.            { we know that operation failed here }
  1346.        mov     bStatusOk, System.False
  1347.     @Done:
  1348.    END;
  1349.    {asm-end}
  1350.  
  1351.    IF NOT(bStatusOk)
  1352.       THEN  BEGIN
  1353.          System.WriteLn(asProgramPrompt+'Unable to set parameters for fixed disk ',dbDriveNum,'.');
  1354.          System.Halt(errBadInitFixedDisk);
  1355.       END;
  1356.    {if-then}
  1357. END;
  1358. { _DoBiosCmdForSetDriveParms }
  1359.  
  1360.  
  1361. PROCEDURE  _SetBiosDriveParametersForFixedDisk0;
  1362. {* Set drive parameters for BIOS. *}
  1363. VAR
  1364.    lpTemp   :   System.Pointer;
  1365.  
  1366. BEGIN
  1367.    {* save original vectors if need it *}
  1368.     IF (ddPrevIntVec41 = NIL)
  1369.           THEN  BEGIN
  1370.             System.WriteLn(asProgramPrompt+'Save fixed drive 0 parameters vector.');
  1371.             Dos.GetIntVec(aDrvParmVec_0,ddPrevIntVec41);
  1372.                 END;
  1373.     {if-then}
  1374.    {* copy a new disk parameters *}
  1375.     _CopyDiskParmsFromIPLforFixedDisk(grecHARD_DISK_PARMS_0,aHardDrive_0-aHardDrive_0);
  1376.     System.WriteLn(asProgramPrompt+'Setup fixed disk 0 parameters.');
  1377.     System.Move(grecHARD_DISK_PARMS_0,
  1378.                 System.Mem[adwABS0_Seg:aLowMemParmVecStoreArea_0],
  1379.                 aDiskParmTableSize);
  1380.     Dos.SetIntVec(aDrvParmVec_0,System.Ptr(adwABS0_Seg,aLowMemParmVecStoreArea_0));
  1381.     Dos.GetIntVec(aDrvParmVec_0,lpTemp);
  1382.     IF (lpTemp <> System.Ptr(adwABS0_Seg,aLowMemParmVecStoreArea_0))
  1383.       THEN  BEGIN
  1384.          System.WriteLn(asProgramPrompt+'Warning! Setup of interrupt vector failed.');
  1385.             END
  1386.       ELSE  BEGIN
  1387.          _DoBiosCmdForSetDriveParms(aHardDrive_0-aHardDrive_0);
  1388.          gbSetupParmsForDrive_0 := System.True;
  1389.             END;
  1390.     {if-then-else}
  1391. END;
  1392. { _SetBiosDriveParametersForFixedDisk0 }
  1393.  
  1394.  
  1395. PROCEDURE  _SetBiosDriveParametersForFixedDisk1;
  1396. {* Set drive parameters for BIOS. *}
  1397. VAR
  1398.    lpTemp   :   System.Pointer;
  1399.  
  1400. BEGIN
  1401.    {* save original vectors if need it *}
  1402.     IF (ddPrevIntVec46 = NIL)
  1403.           THEN  BEGIN
  1404.             System.WriteLn(asProgramPrompt+'Save fixed drive 1 parameters vector.');
  1405.             Dos.GetIntVec(aDrvParmVec_1,ddPrevIntVec46);
  1406.                 END;
  1407.     {if-then}
  1408.    {* copy a new disk parameters *}
  1409.     _CopyDiskParmsFromIPLforFixedDisk(grecHARD_DISK_PARMS_1,aHardDrive_1-aHardDrive_0);
  1410.     System.WriteLn(asProgramPrompt+'Setup fixed disk 1 parameters.');
  1411.     System.Move(grecHARD_DISK_PARMS_1,
  1412.                 System.Mem[adwABS0_Seg:aLowMemParmVecStoreArea_1],
  1413.                 aDiskParmTableSize);
  1414.     Dos.SetIntVec(aDrvParmVec_1,System.Ptr(adwABS0_Seg,aLowMemParmVecStoreArea_1));
  1415.     Dos.GetIntVec(aDrvParmVec_1,lpTemp);
  1416.     IF (lpTemp <> System.Ptr(adwABS0_Seg,aLowMemParmVecStoreArea_1))
  1417.       THEN  BEGIN
  1418.         System.WriteLn(asProgramPrompt+'Warning! Setup of interrupt vector failed.');
  1419.             END
  1420.       ELSE  BEGIN
  1421.          _DoBiosCmdForSetDriveParms(aHardDrive_1-aHardDrive_0);
  1422.          gbSetupParmsForDrive_1 := System.True;
  1423.             END;
  1424.     {if-then-else}
  1425. END;
  1426. { _SetBiosDriveParametersForFixedDisk1 }
  1427.  
  1428.  
  1429. PROCEDURE  _FormatDriveWithNewParameters(dbDriveNum : System.Byte);
  1430. {* General-purpose formatting procedure for selected drive. *}
  1431. VAR
  1432.    {recFORMAT_HARD_DISK_PARMS  :  recHARD_DISK_PARMS;}
  1433.    dwMaxCylNum,
  1434.    dwFormatCylinderNum,
  1435.    dwCylSecValue              :  System.Word;
  1436.    dbMaxHeadNum,
  1437.    dbFormatDriveNum,
  1438.    dbFormatHeadNum,
  1439.    dbFormatSectorNum,
  1440.    dbSectorsPerTrack,
  1441.    dbInterleaveFactor,
  1442.    dbReturnCodeFromBios,
  1443.    dbErrorRetryCount,
  1444.    dbSectorFlag               :  System.Byte;
  1445.    bStatusOk,
  1446.    bMarkTrackAsBad            :  System.Boolean;
  1447.    sTemp                      :  STRING;
  1448.    lpDriveParms               :  System.Pointer;
  1449.  
  1450. BEGIN
  1451.    IF NOT(gbPCATFoundOk)
  1452.      THEN  BEGIN
  1453.       {* force exit *}
  1454.         System.WriteLn(asProgramPrompt+'This may work only for IBM PC/AT or compatible computer.');
  1455.         System.Exit;
  1456.            END;
  1457.   {if-then}
  1458.  
  1459.  {* ask about formatting *}
  1460.     System.Write(asProgramPrompt+'Do you want to format drive ',dbDriveNum,'? (N/Y): ');
  1461.     System.ReadLn(sTemp);
  1462.     IF (System.UpCase(_fnchGetFirstChar(sTemp)) <> achYes)
  1463.      THEN  BEGIN
  1464.       {* force exit *}
  1465.         System.WriteLn(asProgramPrompt+'No drive formatting done.');
  1466.         System.Exit;
  1467.            END;
  1468.     {if-then}
  1469.  
  1470.   {* init internal variables *}
  1471.     dbFormatDriveNum := aHardDrive_0 + dbDriveNum;
  1472.     dbInterleaveFactor := aDefInterleaveFactor;
  1473.     _GetDriveParmsUsingBiosCall(dbFormatDriveNum-aHardDrive_0,dbReturnCodeFromBios,
  1474.                                 dwMaxCylNum,dbMaxHeadNum,dbSectorsPerTrack);
  1475.  
  1476.     IF (dbReturnCodeFromBios <> errOK)
  1477.        THEN  BEGIN
  1478.           System.WriteLn(asProgramPrompt+'Unable to get parameters for fixed disk ',dbDriveNum,'.');
  1479.           System.Halt(errBadGetParmsFixedDisk);
  1480.              END
  1481.        ELSE  System.WriteLn(asProgramPrompt+'Current drive parameters:   Cyls = ',(dwMaxCylNum+2),
  1482.                             ',   Hds = ',dbMaxHeadNum+1,',   Secs = ',dbSectorsPerTrack);
  1483.  
  1484.     {if-then}
  1485.  
  1486.     System.Write(asProgramPrompt+'Select interlave factor (',aBiosSecNumIs1,
  1487.                  '-',dbSectorsPerTrack,', CR=',dbInterleaveFactor,'): ');
  1488.     System.ReadLn(sTemp);
  1489.     IF (sTemp <> asBlank)
  1490.         THEN  BEGIN
  1491.           dbInterleaveFactor := System.Lo(_fndwGetValue(sTemp));
  1492.           IF  (dbInterleaveFactor > dbSectorsPerTrack)
  1493.              THEN  BEGIN
  1494.                 System.WriteLn(asProgramPrompt+'Bad interleave value, reset to default value.');
  1495.                 dbInterleaveFactor := aDefInterleaveFactor;
  1496.                    END;
  1497.           {if-then}
  1498.               END;
  1499.     System.WriteLn(asProgramPrompt+'Selected interlave factor = ',dbInterleaveFactor);
  1500.     {if-then}
  1501.  
  1502.  {* last chance before to begin of formatting proccess *}
  1503.     System.Write(asProgramPrompt+'ALL DATA ON YOUR FIXED DISK WILL BE LOST. ARE YOU SURE? (N/Y): ');
  1504.     System.ReadLn(sTemp);
  1505.     IF (System.UpCase(_fnchGetFirstChar(sTemp)) <> achYes)
  1506.      THEN  BEGIN
  1507.       {* force exit *}
  1508.         System.WriteLn(asProgramPrompt+'Last chance was used. You must be happy!');
  1509.         System.Exit;
  1510.            END;
  1511.     {if-then}
  1512.  
  1513.   {* check drive ready *}
  1514.            System.WriteLn(asProgramPrompt+'... Check Controller/Drive Ready ...');
  1515.            bStatusOk := System.True;
  1516.            asm
  1517.                   mov     ah, aBiosRecalibrateDrive
  1518.                   mov     dl, dbFormatDriveNum
  1519.                   int     aRomDiskDriver          { ROM BIOS disk driver }
  1520.                   mov     ah, aBiosRecalibrateDrive
  1521.                   mov     dl, dbFormatDriveNum
  1522.                   int     aRomDiskDriver          { ROM BIOS disk driver }
  1523.                   mov     ah, aBiosRecalibrateDrive
  1524.                   mov     dl, dbFormatDriveNum
  1525.                   int     aRomDiskDriver          { ROM BIOS disk driver }
  1526.  
  1527.                   mov     ah, aBiosTestIsDriveReady
  1528.                   mov     dl, dbFormatDriveNum
  1529.                   int     aRomDiskDriver          { ROM BIOS disk driver }
  1530.                   jnc    @Done
  1531.                   mov     bStatusOk, System.False
  1532.  
  1533.              @Done:
  1534.            END;
  1535.            {asm-end}
  1536.  
  1537.     IF NOT(bStatusOk)
  1538.          THEN  BEGIN
  1539.           {* force exit *}
  1540.             System.WriteLn(asProgramPrompt+'Controller/Drive not ready.');
  1541.             System.Exit;
  1542.                END;
  1543.         {if-then}
  1544.  
  1545.            dbErrorRetryCount := aRetryOpCount;
  1546.            dbSectorFlag := aGoodSectorFlag;
  1547.            bMarkTrackAsBad := System.False;
  1548.            dbFormatSectorNum := aBiosSecNumIs1;
  1549.            dwFormatCylinderNum := aBiosCylNumIs0;
  1550.            System.FillChar(gdbFormatSectorBuffer,
  1551.                            System.SizeOf(gdbFormatSectorBuffer),
  1552.                            System.Char(aGoodSectorFlag));
  1553.  
  1554.            System.WriteLn(asProgramPrompt+'... Formatting ...');
  1555.  
  1556.  
  1557.            REPEAT
  1558.              dbFormatHeadNum := aBiosHeadNumIs0;
  1559.  
  1560.                REPEAT
  1561.                  System.Write(achCR+asProgramPrompt+'  Cyl: '+_fnsNumToStr4(dwFormatCylinderNum)+
  1562.                                                    '   Hd: '+_fnsNumToStr3(dbFormatHeadNum));
  1563.                   asm
  1564.                       mov     ax, ds
  1565.                       mov     es, ax                { ES = Turbo DS }
  1566.                       mov     bx, OFFSET gdbFormatSectorBuffer
  1567.                       mov     di, bx
  1568.                       mov     al, dbSectorFlag
  1569.                       mov     ah, aBiosSecNumIs1
  1570.                       sub     cx, cx
  1571.                       mov     dx, cx
  1572.                       mov     dl, dbInterleaveFactor
  1573.                       shl     dx, 1                { counts also flags }
  1574.                       mov     cl, dbSectorsPerTrack
  1575.                       mov     si, cx
  1576.                       shl     si, 1                 { check marker of end records }
  1577.                       add     si, bx
  1578.  
  1579.                    @NextLogSecRec:
  1580.                        or     cx, cx
  1581.                        jz    @InitDone
  1582.  
  1583.                        mov    es:[di], ax          { write flag,sector }
  1584.                        inc    ah
  1585.                        dec    cx
  1586.                        add    di, dx               { add interleave }
  1587.  
  1588.                        cmp    di, si
  1589.                        jb    @MatchEntry
  1590.  
  1591.                        sub    di, si               { wrap around }
  1592.                        add    di, bx
  1593.  
  1594.                    @MatchEntry:
  1595.                       jmp    @NextLogSecRec
  1596.  
  1597.                    @InitDone:
  1598.                   END;
  1599.                   {asm-end}
  1600.  
  1601.                   dwCylSecValue := _fnddDoBiosCylSecNum(dwFormatCylinderNum,
  1602.                                                         dbFormatSectorNum);
  1603.                   bStatusOk := System.True;
  1604.                   asm
  1605.                       mov     ax, ds
  1606.                       mov     es, ax                { ES = Turbo DS }
  1607.                       mov     bx, OFFSET gdbFormatSectorBuffer
  1608.                       mov     dh, dbFormatHeadNum
  1609.                       mov     dl, dbFormatDriveNum
  1610.                       mov     cx, dwCylSecValue
  1611.                       mov     al, dbSectorsPerTrack
  1612.                       mov     ah, (aBiosFormatOp)
  1613.                {$IFDEF  FormatLogicTest}
  1614.                       clc                         { flag as success }
  1615.                {$ELSE}
  1616.                       int     aRomDiskDriver      { ROM BIOS disk driver }
  1617.                {$ENDIF} {FormatLogicTest}
  1618.                       jnc     @Done
  1619.                                                     { at this point reading failed }
  1620.                       mov     bStatusOk, System.False
  1621.                       mov     dbReturnCodeFromBios, ah
  1622.  
  1623.                    @Done:
  1624.                   END;
  1625.                   {asm-end}
  1626.                IF  NOT(bStatusOk)
  1627.                  THEN  BEGIN
  1628.                    IF  NOT(bMarkTrackAsBad)
  1629.                       THEN  System.Dec(dbErrorRetryCount);
  1630.                    {if-then}
  1631.                    IF (dbErrorRetryCount <> 0)
  1632.                      THEN  BEGIN
  1633.                        System.WriteLn('  Status: Failed,  Code: ',dbReturnCodeFromBios);
  1634.                        System.WriteLn(asProgramPrompt+'Reset disk subsystem.');
  1635.                        asm
  1636.                                 mov     dl, dbFormatDriveNum
  1637.                                 mov    ah, (aBiosResetOp)
  1638.                                 int    aRomDiskDriver
  1639.                        END;
  1640.                        {asm-end}
  1641.                            END
  1642.                      ELSE  BEGIN
  1643.                           IF (bMarkTrackAsBad)
  1644.                              THEN  BEGIN
  1645.                                 dbErrorRetryCount := aRetryOpCount;
  1646.                                 dbSectorFlag := aGoodSectorFlag;
  1647.                                 bMarkTrackAsBad := System.False;
  1648.                                 System.WriteLn(asBlank);
  1649.                                 System.WriteLn(asProgramPrompt+'Formatting operation failed.');
  1650.                                 System.WriteLn(asProgramPrompt+'Check your controller and/or drive, cables, etc.');
  1651.                                 System.Halt(errFormatFailed);
  1652.                                    END
  1653.                               ELSE BEGIN
  1654.                                 System.WriteLn(asBlank);
  1655.                                 System.WriteLn(asProgramPrompt+'Mark all sectors on this track as bad.');
  1656.                                 bMarkTrackAsBad := System.True;
  1657.                                 dbSectorFlag := aBadSectorFlag;
  1658.                                    END;
  1659.                           {if-then-else}
  1660.                            END;
  1661.                    {if-then}
  1662.                        END
  1663.                {if-then}
  1664.                  ELSE   BEGIN
  1665.                    IF (bMarkTrackAsBad)
  1666.                      THEN    BEGIN
  1667.                         dbErrorRetryCount := aRetryOpCount;
  1668.                         dbSectorFlag := aGoodSectorFlag;
  1669.                         bMarkTrackAsBad := System.False;
  1670.                         System.WriteLn(asBlank);
  1671.                         System.WriteLn(asProgramPrompt+'..Formatting continue..');
  1672.                              END
  1673.                   ELSE    BEGIN
  1674.                    System.Inc(dbFormatHeadNum);
  1675.                           END;
  1676.                    {if-then-else}
  1677.                         END;
  1678.                {if-then-else}
  1679.  
  1680.                bStatusOk := System.True;
  1681.  
  1682.              UNTIL (NOT(bStatusOk) OR (dbFormatHeadNum > dbMaxHeadNum));
  1683.              {repeat-until}
  1684.  
  1685.              System.Inc(dwFormatCylinderNum);
  1686.            UNTIL ((dwFormatCylinderNum > dwMaxCylNum) OR NOT(bStatusOk));
  1687.            {repeat-until}
  1688.  
  1689.     System.WriteLn(asBlank);
  1690.     System.WriteLn(asProgramPrompt+'Format complete.');
  1691.  
  1692.     System.WriteLn(asProgramPrompt+'Reset disk subsystem.');
  1693.     asm
  1694.              mov     dl, dbFormatDriveNum
  1695.              mov     ah, (aBiosResetOp)
  1696.              int     aRomDiskDriver
  1697.     END;
  1698.     {asm-end}
  1699.  
  1700.     System.Write(asProgramPrompt+'Verify after formatting? (N/Y): ');
  1701.     System.ReadLn(sTemp);
  1702.     IF (System.UpCase(_fnchGetFirstChar(sTemp)) = achYes)
  1703.       THEN  BEGIN
  1704.            dbFormatSectorNum := aBiosSecNumIs1;
  1705.            dwFormatCylinderNum := aBiosCylNumIs0;
  1706.            System.FillChar(gdbFormatSectorBuffer,
  1707.                            System.SizeOf(gdbFormatSectorBuffer),
  1708.                            System.Char(aGoodSectorFlag));
  1709.  
  1710.            System.WriteLn(asProgramPrompt+'... Verifying ...');
  1711.  
  1712.            REPEAT
  1713.              dbFormatHeadNum := aBiosHeadNumIs0;
  1714.  
  1715.                REPEAT
  1716.                  System.Write(achCR+asProgramPrompt+'  Cyl: '+_fnsNumToStr4(dwFormatCylinderNum)+
  1717.                                                    '   Hd: '+_fnsNumToStr3(dbFormatHeadNum));
  1718.  
  1719.                   dwCylSecValue := _fnddDoBiosCylSecNum(dwFormatCylinderNum,
  1720.                                                         dbFormatSectorNum);
  1721.                   bStatusOk := System.True;
  1722.                   asm
  1723.                       mov     ax, adwTestMemBufSeg
  1724.                       mov     es, ax                { ES = Turbo DS }
  1725.                       mov     bx, adwTestMemBufOfs
  1726.                       mov     dh, dbFormatHeadNum
  1727.                       mov     dl, dbFormatDriveNum
  1728.                       mov     cx, dwCylSecValue
  1729.                       mov     al, dbSectorsPerTrack
  1730.                       mov     ah, (aBiosVerifyOp)
  1731.                {$IFDEF  VerifyLogicTest}
  1732.                       clc                         { flag as success }
  1733.                {$ELSE}
  1734.                       int     aRomDiskDriver      { ROM BIOS disk driver }
  1735.                {$ENDIF} {VerifyLogicTest}
  1736.                       jnc     @Done
  1737.                                                     { at this point reading failed }
  1738.                       mov     bStatusOk, System.False
  1739.                       mov     dbReturnCodeFromBios, ah
  1740.  
  1741.                    @Done:
  1742.                   END;
  1743.                   {asm-end}
  1744.                IF  NOT(bStatusOk)
  1745.                  THEN  BEGIN
  1746.                    System.WriteLn('  Status: Failed,  Code: ',dbReturnCodeFromBios);
  1747.                    bStatusOk := System.True;
  1748.                    System.WriteLn(asProgramPrompt+'Reset disk subsystem.');
  1749.                    asm
  1750.                             mov     dl, dbFormatDriveNum
  1751.                             mov        ah, (aBiosResetOp)
  1752.                             int        aRomDiskDriver
  1753.                    END;
  1754.                    {asm-end}
  1755.                        END;
  1756.                {if-then}
  1757.                System.Inc(dbFormatHeadNum);
  1758.              UNTIL (NOT(bStatusOk) OR (dbFormatHeadNum > dbMaxHeadNum));
  1759.              {repeat-until}
  1760.  
  1761.              System.Inc(dwFormatCylinderNum);
  1762.            UNTIL ((dwFormatCylinderNum > dwMaxCylNum) OR NOT(bStatusOk));
  1763.            {repeat-until}
  1764.  
  1765.            System.WriteLn(asBlank);
  1766.            System.WriteLn(asProgramPrompt+'Drive verifying done.');
  1767.            END;
  1768.     {if-then}
  1769. END;
  1770. { _FormatDriveWithNewParameters }
  1771.  
  1772.  
  1773. PROCEDURE  _DisplayCurrentSettingsForBootLoader;
  1774. {* Output miscellaneous current setting. *}
  1775. VAR
  1776.     recDriveParms_0,
  1777.     recDriveParms_1   :  recHARD_DISK_PARMS;
  1778.     dbBitFlags        :  System.Byte;
  1779.     sTemp             :  STRING;
  1780.  
  1781. BEGIN
  1782.   dbBitFlags := System.Mem[System.Seg(_IPL_Code):aInitBitFlagsOfs];
  1783.   System.Move(System.Mem[System.Seg(_IPL_Code):
  1784.               (aBootDiskDriveTableOfs+(aDiskParmTableSize*(aHardDrive_0-aHardDrive_0)))],
  1785.               recDriveParms_0,
  1786.               aDiskParmTableSize);
  1787.   System.Move(System.Mem[System.Seg(_IPL_Code):
  1788.               (aBootDiskDriveTableOfs+(aDiskParmTableSize*(aHardDrive_1-aHardDrive_0)))],
  1789.               recDriveParms_1,
  1790.               aDiskParmTableSize);
  1791.  
  1792.    System.WriteLn(asProgramPrompt+'Current settings are the following:');
  1793.    System.WriteLn(asProgramPrompt+' --> Global Flags <--');
  1794.  
  1795.    IF  ((dbBitFlags AND btAskBootDisk) <> 0)
  1796.      THEN  sTemp := 'ON'
  1797.      ELSE  sTemp := 'OFF';
  1798.    {if-then}
  1799.    System.WriteLn(asProgramPrompt+'  Boot Drive Prompt is '+sTemp+'.');
  1800.    IF  ((dbBitFlags AND btSetDiskType_0) <> 0)
  1801.      THEN  sTemp := 'ON'
  1802.      ELSE  sTemp := 'OFF';
  1803.    {if-then}
  1804.    System.WriteLn(asProgramPrompt+'  Set disk type for drive 0 is '+sTemp+'.');
  1805.    IF  ((dbBitFlags AND btSetDiskType_1) <> 0)
  1806.      THEN  sTemp := 'ON'
  1807.      ELSE  sTemp := 'OFF';
  1808.    {if-then}
  1809.    System.WriteLn(asProgramPrompt+'  Set disk type for drive 1 is '+sTemp+'.');
  1810.  
  1811.    System.WriteLn(asProgramPrompt+' --> Drive Parameter <--        Drive 0        Drive 1');
  1812.  
  1813.    System.WriteLn(asProgramPrompt+'  Number of cylinders      =   '+
  1814.                   _fnsNumToStr5(recDriveParms_0.dwMAX_CYLS_NUM)+asSpaces10,
  1815.                   _fnsNumToStr5(recDriveParms_1.dwMAX_CYLS_NUM));
  1816.    System.WriteLn(asProgramPrompt+'  Number of heads          =   '+
  1817.                   _fnsNumToStr5(recDriveParms_0.dbMAX_HEADS_NUM)+asSpaces10,
  1818.                   _fnsNumToStr5(recDriveParms_1.dbMAX_HEADS_NUM));
  1819.    System.WriteLn(asProgramPrompt+'  Starting WPC for XT      =   '+
  1820.                   _fnsNumToStr5(recDriveParms_0.dwSTART_WRC_XT)+asSpaces10,
  1821.                   _fnsNumToStr5(recDriveParms_1.dwSTART_WRC_XT));
  1822.    System.WriteLn(asProgramPrompt+'  Starting WPC             =   '+
  1823.                   _fnsNumToStr5(recDriveParms_0.dwSTART_WRC)+asSpaces10,
  1824.                   _fnsNumToStr5(recDriveParms_1.dwSTART_WRC));
  1825.    System.WriteLn(asProgramPrompt+'  ECC data burst length    =   '+
  1826.                   _fnsNumToStr5(recDriveParms_0.dbMAX_ECC_DATA_BURST_LEN)+asSpaces10,
  1827.                   _fnsNumToStr5(recDriveParms_1.dbMAX_ECC_DATA_BURST_LEN));
  1828.    System.WriteLn(asProgramPrompt+'  Control Byte             =   '+
  1829.                   _fnsNumToStr5(recDriveParms_0.dbCONTROL_BYTE)+asSpaces10,
  1830.                   _fnsNumToStr5(recDriveParms_1.dbCONTROL_BYTE));
  1831.    System.WriteLn(asProgramPrompt+'  Standard time-out for XT =   '+
  1832.                   _fnsNumToStr5(recDriveParms_0.dbSTD_TIME_OUT_XT)+asSpaces10,
  1833.                   _fnsNumToStr5(recDriveParms_1.dbSTD_TIME_OUT_XT));
  1834.    System.WriteLn(asProgramPrompt+'  Format time-out for XT   =   '+
  1835.                   _fnsNumToStr5(recDriveParms_0.dbFMT_TIME_OUT_XT)+asSpaces10,
  1836.                   _fnsNumToStr5(recDriveParms_1.dbFMT_TIME_OUT_XT));
  1837.    System.WriteLn(asProgramPrompt+'  Check time-out for XT    =   '+
  1838.                   _fnsNumToStr5(recDriveParms_0.dbCHECK_TIME_OUT_XT)+asSpaces10,
  1839.                   _fnsNumToStr5(recDriveParms_1.dbCHECK_TIME_OUT_XT));
  1840.    System.WriteLn(asProgramPrompt+'  Landing zone             =   '+
  1841.                   _fnsNumToStr5(recDriveParms_0.dwLANDING_ZONE)+asSpaces10,
  1842.                   _fnsNumToStr5(recDriveParms_1.dwLANDING_ZONE));
  1843.    System.WriteLn(asProgramPrompt+'  Number of sectors/track  =   '+
  1844.                   _fnsNumToStr5(recDriveParms_0.dbSECTORS_PER_TRACK),asSpaces10,
  1845.                   _fnsNumToStr5(recDriveParms_1.dbSECTORS_PER_TRACK));
  1846.    System.WriteLn(asProgramPrompt+'  Reserved byte            =   '+
  1847.                   _fnsNumToStr5(recDriveParms_0.dbPARM_RESERVED),asSpaces10,
  1848.                   _fnsNumToStr5(recDriveParms_1.dbPARM_RESERVED));
  1849. END;
  1850. { _DisplayCurrentSettingsForBootLoader }
  1851.  
  1852.  
  1853. PROCEDURE  _NoticeAboutAdvancedVersion;
  1854. {* Output notice to explain. *}
  1855. BEGIN
  1856.    System.WriteLn(asProgramPrompt+'Available only in advanced version of '+asProgram);
  1857. END;
  1858. { _NoticeAboutAdvancedVersion }
  1859.  
  1860.  
  1861.  
  1862. {*============================== MAIN PART =============================*}
  1863.  
  1864. BEGIN
  1865.  
  1866.   {* copyright message *}
  1867.     _CopyrightDisplay;
  1868.  
  1869.  
  1870.   {* get a length of boot code *}
  1871.      gdwOurBootRecLen := System.Ofs(_DummyProc) - System.Ofs(_IPL_Code);
  1872.  
  1873.  
  1874.   {* test bootstrap procedure *}
  1875. {$IFDEF   DebugVersion}
  1876.     System.WriteLn(asProgramPrompt+'Debugging of boostrap procedure.');
  1877.     asm
  1878.       mov        ax,  aDebugOn        { no relocated code }
  1879.     END;
  1880.     {asm-end}
  1881.  
  1882.     _IPL_Code;
  1883.  
  1884.    System.Halt(errBootStrapDebug);
  1885. {$ENDIF}  {DebugVersion}
  1886.  
  1887.   {* test for match length of IPL *}
  1888.      IF  (gdwOurBootRecLen > adwPartitionTable)
  1889.        THEN  BEGIN
  1890.          System.WriteLn(asProgramPrompt+'Bad size of loader code please re-code.');
  1891.          System.Halt(errMismatchLoaderCode);
  1892.              END;
  1893.      {if-then}
  1894.  
  1895.   {* some housekeeping *}
  1896.      gbPCATFoundOk := (gdbPcType = aPcTypeIsAT);
  1897.  
  1898.   {* Read original master boot record *}
  1899.       _ReadMBRfromFixedDisk;
  1900.  
  1901.   {* make a backup copy *}
  1902.     System.Move(grecFixedDiskBoot,grecOrigFixedDiskBoot,System.SizeOf(grecFixedDiskBoot));
  1903.     gbOriginalMBRpresent := System.True;
  1904.  
  1905.   {* check for presence of installed loader *}
  1906.     System.Move(grecFixedDiskBoot,gsTempInput[1],aMaxTpStrLen);
  1907.     gsTempInput[0] := System.Char(aMaxTpStrLen);
  1908.     IF  (System.Pos(asSearchNotice,gsTempInput) <> 0)
  1909.       THEN  BEGIN
  1910.          System.WriteLn(asProgramPrompt+asProgram+' loader found on fixed disk 0.');
  1911.          System.Write(asProgramPrompt+'Copy drive types/settings from installed copy (Y/N): ');
  1912.          System.ReadLn(gsTempInput);
  1913.  
  1914.          IF  (System.UpCase(_fnchGetFirstChar(gsTempInput)) <> achNo)
  1915.             THEN  BEGIN
  1916.                System.WriteLn(asProgramPrompt+'Copy already defined drive types/settings.');
  1917.                _CopyDriveTypesAndSettingsFromMBR;
  1918.                   END;
  1919.          {if-then}
  1920.             END
  1921.       ELSE
  1922.          System.WriteLn(asProgramPrompt+asProgram+' loader not present.');
  1923.     {if-then}
  1924.  
  1925.   {$IFDEF   FormatLogicTest}
  1926.       System.WriteLn(asProgramPrompt+'Logical test of format operations selected.');
  1927.   {$ENDIF} {FormatLogicTest}
  1928.  
  1929.   {$IFDEF   VerifyLogicTest}
  1930.       System.WriteLn(asProgramPrompt+'Logical test of verify operations selected.');
  1931.   {$ENDIF} {VerifyLogicTest}
  1932.  
  1933.   System.WriteLn(asProgramPrompt+'Press <ENTER> to continue.');
  1934.   System.ReadLn;
  1935.  
  1936.   gbUserAskExit := System.False;
  1937.  
  1938.   {* user menu and main command-driven loop *}
  1939.  
  1940.   WHILE  NOT(gbUserAskExit)  DO
  1941.   BEGIN
  1942.      System.WriteLn(asBlank);
  1943.      System.WriteLn('******************** Common User Menu ******************************');
  1944.      System.WriteLn('['+ achZero  +']  Enable/Disable Boot Drive Ask');
  1945.      System.WriteLn('['+ achOne   +']  Save Master Boot Record (MBR)');
  1946.      System.WriteLn('['+ achTwo   +']  Restore Master Boot Record (MBR)');
  1947.      System.WriteLn('['+ achThree +']  Set/Update parameters for drive 0');
  1948.      System.WriteLn('['+achFour   +']  Set/Update parameters for drive 1');
  1949.      System.WriteLn('['+achFive   +']  Enable/Disable type setup for drive 0 (at boot time)');
  1950.      System.WriteLn('['+achSix    +']  Enable/Disable type setup for drive 1 (at boot time)');
  1951.      System.WriteLn('['+achSeven  +']  Init/Update Master Partition');
  1952.      System.WriteLn('['+achEight  +']  Write/Update Master Boot Record (MBR)');
  1953.      System.WriteLn('['+achNine   +']  Quit');
  1954.   {$IFDEF  AdvancedUserVersion}
  1955.      System.WriteLn('******************** Advanced User Menu ******************************');
  1956.      System.WriteLn('['+achDisplayCmd+']  Display current boot loader settings');
  1957.      System.WriteLn('['+achCopyCmd   +']  Move Original Copy to MBR Buffer');
  1958.      System.WriteLn('['+achTestCmd   +']  Write new Master Boot Record (MBR) to file');
  1959.      System.WriteLn('['+achFormatCmd +']  Format drive 0/1 with new parameters');
  1960.      System.WriteLn('['+achSetCmd    +']  Set drive 0/1 parameters for BIOS');
  1961.   {$ENDIF} {AdvancedUserVersion}
  1962.      System.WriteLn('--> Command Prompt <--');
  1963.      System.Write('Select your option: ');
  1964.  
  1965.      System.ReadLn(gsTempInput);
  1966.      gsTempInput := System.UpCase(_fnchGetFirstChar(gsTempInput));
  1967.  
  1968.      CASE  gsTempInput[1] OF
  1969.       achDisplayCmd :     BEGIN
  1970.                        {$IFDEF  AdvancedUserVersion}
  1971.                            _DisplayCurrentSettingsForBootLoader;
  1972.                        {$ELSE}
  1973.                            _NoticeAboutAdvancedVersion;
  1974.                        {$ENDIF} {AdvancedUserVersion}
  1975.                           END;
  1976.          achSetCmd  :     BEGIN
  1977.                        {$IFDEF  AdvancedUserVersion}
  1978.                             System.Write(asProgramPrompt+'Select drive (0/1/CR=none): ');
  1979.                             System.ReadLn(gsTempInput);
  1980.                             gsTempInput := System.UpCase(_fnchGetFirstChar(gsTempInput));
  1981.                             CASE  gsTempInput[1]  OF
  1982.                                 achZero  :   BEGIN
  1983.                                           _SetBiosDriveParametersForFixedDisk0;
  1984.                                              END;
  1985.                                 achOne  :   BEGIN
  1986.                                           _SetBiosDriveParametersForFixedDisk1;
  1987.                                              END;
  1988.                              ELSE
  1989.                                  System.WriteLn(asProgramPrompt+'None drive selected. Nothing done.');
  1990.                              END;
  1991.                              {case-of}
  1992.                        {$ELSE}
  1993.                            _NoticeAboutAdvancedVersion;
  1994.                        {$ENDIF} {AdvancedUserVersion}
  1995.                           END;
  1996.        achFormatCmd :     BEGIN
  1997.                        {$IFDEF   AdvancedUserVersion}
  1998.                             System.Write(asProgramPrompt+'Select drive (0/1/CR=none): ');
  1999.                             System.ReadLn(gsTempInput);
  2000.                             gsTempInput := System.UpCase(_fnchGetFirstChar(gsTempInput));
  2001.                             CASE  gsTempInput[1]  OF
  2002.                                 achZero  :   BEGIN
  2003.                                         {$IFDEF   FormatLogicTest}
  2004.                                             gbSetupParmsForDrive_0 := System.True;
  2005.                                         {$ENDIF} {FormatLogicTest}
  2006.                                            IF (gbSetupParmsForDrive_0)
  2007.                                               THEN  BEGIN
  2008.                                           _FormatDriveWithNewParameters(aHardDrive_0-aHardDrive_0);
  2009.                                                     END
  2010.                                                ELSE  BEGIN
  2011.                                           System.WriteLn(asProgramPrompt+'You must set the drive parameters before.');
  2012.                                                      END;
  2013.                                            {if-then}
  2014.                                              END;
  2015.                                 achOne  :   BEGIN
  2016.                                         {$IFDEF   FormatLogicTest}
  2017.                                             gbSetupParmsForDrive_1 := System.True;
  2018.                                         {$ENDIF} {FormatLogicTest}
  2019.                                            IF (gbSetupParmsForDrive_1)
  2020.                                               THEN  BEGIN
  2021.                                           _FormatDriveWithNewParameters(aHardDrive_1-aHardDrive_0);
  2022.                                                     END
  2023.                                                ELSE  BEGIN
  2024.                                           System.WriteLn(asProgramPrompt+'You must set the drive parameters before.');
  2025.                                                      END;
  2026.                                            {if-then}
  2027.                                              END;
  2028.                              ELSE
  2029.                                  System.Write(asProgramPrompt+'None drive selected. Nothing done.');
  2030.                              END;
  2031.                              {case-of}
  2032.                        {$ELSE}
  2033.                            _NoticeAboutAdvancedVersion;
  2034.                        {$ENDIF} {AdvancedUserVersion}
  2035.                           END;
  2036.          achTestCmd  :    BEGIN
  2037.                        {$IFDEF AdvancedUserVersion}
  2038.                            _CopyLoaderCodeToMBR;
  2039.                            System.WriteLn(asProgramPrompt+'Copy constructed MBR to file (for test purpose).');
  2040.                            _SaveMBRtoFile;
  2041.                        {$ELSE}
  2042.                            _NoticeAboutAdvancedVersion;
  2043.                        {$ENDIF} {AdvancedUserVersion}
  2044.                           END;
  2045.          achCopyCmd :     BEGIN
  2046.                        {$IFDEF AdvancedUserVersion}
  2047.                              IF (gbOriginalMBRpresent)
  2048.                                THEN  BEGIN
  2049.                                  System.WriteLn(asProgramPrompt+'Copy to MBR buffer.');
  2050.                                  System.Move(grecOrigFixedDiskBoot,
  2051.                                              grecFixedDiskBoot,
  2052.                                              System.SizeOf(grecFixedDiskBoot));
  2053.                                      END
  2054.                                ELSE  BEGIN
  2055.                                  System.WriteLn(asProgramPrompt+'Original MBR not saved at start-up.');
  2056.                                      END;
  2057.                              {if-then-else}
  2058.                        {$ELSE}
  2059.                            _NoticeAboutAdvancedVersion;
  2060.                        {$ENDIF} {AdvancedUserVersion}
  2061.                           END;
  2062.              achZero  :   BEGIN
  2063.                              _ToggleBootDriveAsk;
  2064.                           END;
  2065.              achOne :     BEGIN
  2066.                       {* save original boot record *}
  2067.                         System.WriteLn(asProgramPrompt+'Saving of original MBR.');
  2068.                         _SaveMBRtoFile;
  2069.                           END;
  2070.              achTwo :     BEGIN
  2071.                                 _RestoreMBRfromFile;
  2072.                           END;
  2073.               achThree :  BEGIN
  2074.                        {* get the user parameters for the disk drive(s) in the system *}
  2075.                            _GetDiskDriveParameters(aHardDrive_0-aHardDrive_0);
  2076.                           END;
  2077.              achFour  :   BEGIN
  2078.                        {* get the user parameters for the disk drive(s) in the system *}
  2079.                            _GetDiskDriveParameters(aHardDrive_1-aHardDrive_0);
  2080.                           END;
  2081.              achFive  :   BEGIN
  2082.                               _AttachOrDeAttachDrive(aHardDrive_0-aHardDrive_0);
  2083.                           END;
  2084.              achSix  :    BEGIN
  2085.                               _AttachOrDeAttachDrive(aHardDrive_1-aHardDrive_0);
  2086.                           END;
  2087.              achSeven  :  BEGIN
  2088.                               _InitMasterPartitionRecord;
  2089.                           END;
  2090.              achEight  :  BEGIN
  2091.                       {* ask user about installation *}
  2092.                          System.Write(asProgramPrompt+'Install '+asProgram+'. Are you sure? (N/Y): ');
  2093.                          System.ReadLn(gsTempInput);
  2094.                          IF  (System.UpCase(_fnchGetFirstChar(gsTempInput)) = achYes)
  2095.                            THEN  BEGIN
  2096.                               {* make a new boot record *}
  2097.                                 _CopyLoaderCodeToMBR;
  2098.  
  2099.                               {* Ask user about writing. *}
  2100.                                  System.Write(asProgramPrompt+'Write a new IPL. Are you sure? (N/Y): ');
  2101.                                  System.ReadLn(gsTempInput);
  2102.  
  2103.                                  IF  (System.UpCase(_fnchGetFirstChar(gsTempInput)) = achYes)
  2104.                                    THEN  BEGIN
  2105.                                       _WriteMBRtoFixedDisk;
  2106.                                          END
  2107.                                    ELSE  BEGIN
  2108.                                       System.WriteLn(asProgramPrompt+'Aborted by user.');
  2109.                                          END;
  2110.                                  {if-then-else}
  2111.                                  END
  2112.                            ELSE  BEGIN
  2113.                              System.WriteLn(asProgramPrompt+'Aborted by user.');
  2114.                                  END;
  2115.                          {if-then-else}
  2116.                           END;
  2117.              achNine  :   BEGIN
  2118.                        gbUserAskExit := System.True;
  2119.                           END;
  2120.        ELSE
  2121.           System.WriteLn(asProgramPrompt+'Invalid selection of menu item.');
  2122.      END;
  2123.      IF NOT(gbUserAskExit)
  2124.        THEN  BEGIN
  2125.           System.Write(asProgramPrompt+'Press <CR> to continue.');
  2126.           System.ReadLn;
  2127.              END;
  2128.      {if-then}
  2129.  
  2130.   END;
  2131.   {while-do}
  2132.  
  2133.   {* final report *}
  2134.     System.WriteLn(asProgramPrompt+'Done.');
  2135.  
  2136.   {* System.Halt(errTerminateOk); *}
  2137. END.
  2138.